From 9239e131209e88d88e810297cbc00f581159cf41 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Thu, 24 Feb 2022 17:49:38 +0100 Subject: [PATCH 01/49] Added authorization-utils refs #22871 --- pom.xml | 6 ++++++ .../application/request/RequestContextRetriever.java | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/pom.xml b/pom.xml index 895cdd9..24be6f2 100644 --- a/pom.xml +++ b/pom.xml @@ -66,6 +66,12 @@ org.gcube.common common-authorization + + + org.gcube.common + authorization-utils + [1.0.0,2.0.0-SNAPSHOT) + org.gcube.data.publishing diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index 70e983d..c0de5a5 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -18,6 +18,7 @@ import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.smartgears.Constants; @@ -75,10 +76,14 @@ public class RequestContextRetriever extends RequestHandler { else if (scope!=null) ScopeProvider.instance.set(scope); + SecretManager.instance.get(); } @Override public void handleResponse(ResponseEvent e) { + // This should be enough but maintaining also the old resets + SecretManager.instance.get().reset(); + SecurityTokenProvider.instance.reset(); AuthorizationProvider.instance.reset(); AccessTokenProvider.instance.reset(); From 29ac4def10a481c672af01aae0c188efaeed4034 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 25 Feb 2022 15:07:09 +0100 Subject: [PATCH 02/49] Intregrated authorization-utils in place of ad-hoc code --- CHANGELOG.md | 5 + pom.xml | 4 +- .../request/RequestContextRetriever.java | 129 +++++------------- .../org/gcube/smartgears/utils/GcubeJwt.java | 79 ----------- 4 files changed, 42 insertions(+), 175 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/utils/GcubeJwt.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 5a7a06f..ebfd6dd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm # Changelog for Common Smartgears +## [v3.2.0-SNAPSHOT] + +- Added SecretManager thread local from authorization-utils [#22871] + + ## [v3.1.2-SNAPSHOT] - 2022-01-19 - enabled policy check on smartgears diff --git a/pom.xml b/pom.xml index 24be6f2..65aac6f 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.gcube.core common-smartgears - 3.1.2-SNAPSHOT + 3.2.0-SNAPSHOT SmartGears @@ -70,7 +70,7 @@ org.gcube.common authorization-utils - [1.0.0,2.0.0-SNAPSHOT) + [2.0.0-SNAPSHOT,3.0.0-SNAPSHOT) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index c0de5a5..2e57d75 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -1,31 +1,21 @@ package org.gcube.smartgears.handlers.application.request; -import static org.gcube.common.authorization.client.Constants.authorizationService; import static org.gcube.smartgears.Constants.scope_header; import static org.gcube.smartgears.Constants.token_header; import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; import java.util.Base64; import javax.xml.bind.annotation.XmlRootElement; -import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; -import org.gcube.common.authorization.client.exceptions.ObjectNotFound; -import org.gcube.common.authorization.library.AuthorizationEntry; -import org.gcube.common.authorization.library.provider.AccessTokenProvider; -import org.gcube.common.authorization.library.provider.AuthorizationProvider; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.authorization.library.provider.UserInfo; -import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.common.authorization.utils.secret.GCubeSecret; +import org.gcube.common.authorization.utils.secret.JWTSecret; import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.common.scope.impl.ScopeBean; import org.gcube.smartgears.Constants; import org.gcube.smartgears.handlers.application.RequestEvent; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.ResponseEvent; -import org.gcube.smartgears.utils.GcubeJwt; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,8 +41,8 @@ public class RequestContextRetriever extends RequestHandler { String authHeader = call.request().getHeader(Constants.authorization_header); log.trace("authorization header is {}",authHeader); - log.trace("token header is {}",token); - log.trace("scope header is {}",scope); + log.trace("token header is {}", token); + log.trace("scope header is {}", scope); String retrievedUser = null; String accessToken = null; @@ -68,92 +58,43 @@ public class RequestContextRetriever extends RequestHandler { } } - //Gives priority to the umaToken - if (accessToken!=null) { - this.retreiveAndSetInfoUmaToken(accessToken, token, call); - } else if (token!=null) - this.retreiveAndSetInfoGcubeToken(token, retrievedUser, call); - else if (scope!=null) - ScopeProvider.instance.set(scope); + SecretManager secretManager = SecretManager.instance.get(); + + if (accessToken!=null) { + JWTSecret jwtSecret = new JWTSecret(accessToken); + secretManager.addSecret(jwtSecret); + } + + if (token!=null) { + GCubeSecret gCubeSecret = new GCubeSecret(token); + secretManager.addSecret(gCubeSecret); + try { + if (retrievedUser != null && !gCubeSecret.getClientInfo().getId().equals(retrievedUser)) { + internal_server_error.fire("user and token owner are not the same"); + } + }catch (Exception e) { + internal_server_error.fire(e.getMessage()); + } + } + + if(accessToken==null && token==null) { + if(scope!=null) { + ScopeProvider.instance.set(scope); + } + }else { + try { + secretManager.set(); + } catch (Exception e) { + internal_server_error.fire(e.getMessage()); + } + } - SecretManager.instance.get(); } @Override public void handleResponse(ResponseEvent e) { - // This should be enough but maintaining also the old resets - SecretManager.instance.get().reset(); - - SecurityTokenProvider.instance.reset(); - AuthorizationProvider.instance.reset(); - AccessTokenProvider.instance.reset(); - ScopeProvider.instance.reset(); log.debug("resetting all the Thread local for this call."); + SecretManager.instance.get().reset(); } - - private void retreiveAndSetInfoGcubeToken(String token, String retrievedUser, RequestEvent call){ - log.trace("retrieving context using token {} ", token); - AuthorizationEntry authEntry = null; - try{ - authEntry = authorizationService().get(token); - if (retrievedUser != null && !authEntry.getClientInfo().getId().equals(retrievedUser)) - throw new Exception("user and token owner are not the same"); - }catch(ObjectNotFound onf){ - log.warn("rejecting call to {}, invalid token {}",call.context().name(),token); - invalid_request_error.fire(call.context().name()+" invalid token : "+token); - }catch(Exception e){ - log.error("error contacting authorization service",e); - internal_server_error.fire("error contacting authorization service"); - } - - AuthorizationProvider.instance.set(new Caller(authEntry.getClientInfo(), authEntry.getQualifier())); - SecurityTokenProvider.instance.set(token); - ScopeProvider.instance.set(authEntry.getContext()); - log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), authEntry.getContext()); - } - - private void retreiveAndSetInfoUmaToken(String accessToken, String gcubeToken, RequestEvent call){ - log.debug("using UMA token for authorization"); - log.trace("retrieving context using uma token {} ", accessToken); - - AccessTokenProvider.instance.set(accessToken); - SecurityTokenProvider.instance.set(gcubeToken); - parseAccessTokenAndSet(accessToken); - log.info("retrieved request authorization info {} in scope {} ", AuthorizationProvider.instance.get(), ScopeProvider.instance.get()); - } - - private void parseAccessTokenAndSet(String umaToken) { - - String realUmaTokenEncoded = umaToken.split("\\.")[1]; - - String realUmaToken = new String(Base64.getDecoder().decode(realUmaTokenEncoded.getBytes())); - - ObjectMapper mapper = new ObjectMapper(); - - - GcubeJwt jwt = null; - try { - jwt = mapper.readValue(realUmaToken, GcubeJwt.class); - }catch(Exception e){ - log.error("error decoding uma token",e); - internal_server_error.fire("error parsing access token"); - } - - - ScopeBean scopeBean = null; - try { - scopeBean = new ScopeBean(jwt.getContext()); - }catch(Exception e){ - log.error("error decoding uma token",e); - internal_server_error.fire("invalid context in access token"); - } - - AuthorizationProvider.instance.set(new Caller(new UserInfo(jwt.getUsername(), jwt.getRoles(), jwt.getEmail(), jwt.getFirstName(), jwt.getLastName()), "token")); - - ScopeProvider.instance.set(scopeBean.toString()); - - } - - } diff --git a/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java b/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java deleted file mode 100644 index b86540c..0000000 --- a/src/main/java/org/gcube/smartgears/utils/GcubeJwt.java +++ /dev/null @@ -1,79 +0,0 @@ -package org.gcube.smartgears.utils; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.gcube.com.fasterxml.jackson.annotation.JsonIgnoreProperties; -import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; - -@JsonIgnoreProperties(ignoreUnknown = true) -public class GcubeJwt { - - protected final static List MINIMAL_ROLES = Arrays.asList("Member"); - - @JsonProperty("aud") - private String context; - - @JsonProperty("resource_access") - private Map contextAccess = new HashMap<>(); - - @JsonProperty("preferred_username") - private String username; - - @JsonProperty("given_name") - private String firstName; - - @JsonProperty("family_name") - private String lastName; - - @JsonProperty("email") - private String email; - - public List getRoles(){ - return contextAccess.get(this.context) == null ? MINIMAL_ROLES : contextAccess.get(this.context).roles; - } - - public String getContext() { - try { - return URLDecoder.decode(context, StandardCharsets.UTF_8.toString()); - }catch (UnsupportedEncodingException e) { - return context; - } - } - - public String getUsername() { - return username; - } - - public String getFirstName() { - return firstName; - } - - public String getLastName() { - return lastName; - } - - public String getEmail() { - return email; - } - - @Override - public String toString() { - return "GcubeJwt [context=" + getContext() + ", roles=" + getRoles() + ", username=" + username - + ", firstName=" + firstName + ", lastName=" + lastName + ", email=" + email + "]"; - } - - public static class Roles { - - @JsonProperty("roles") - List roles = new ArrayList<>(); - - } - -} From b703d6605b9355c7e87cba76bbf0ee45c9014561 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 25 Feb 2022 16:21:33 +0100 Subject: [PATCH 03/49] upgraded gcube-bom version --- pom.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 65aac6f..39ef440 100644 --- a/pom.xml +++ b/pom.xml @@ -19,7 +19,7 @@ org.gcube.distribution gcube-bom - 2.0.1 + 2.1.0-SNAPSHOT pom import @@ -70,7 +70,6 @@ org.gcube.common authorization-utils - [2.0.0-SNAPSHOT,3.0.0-SNAPSHOT) From 405a65282dfcfec4b2928e1b8ab2c865cae865d1 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Mon, 28 Feb 2022 13:26:40 +0100 Subject: [PATCH 04/49] Fixed code to instantiate SecretManager --- .../application/request/RequestContextRetriever.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index 2e57d75..5860b5b 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -9,6 +9,7 @@ import java.util.Base64; import javax.xml.bind.annotation.XmlRootElement; import org.gcube.common.authorization.utils.manager.SecretManager; +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.authorization.utils.secret.GCubeSecret; import org.gcube.common.authorization.utils.secret.JWTSecret; import org.gcube.common.scope.api.ScopeProvider; @@ -58,7 +59,7 @@ public class RequestContextRetriever extends RequestHandler { } } - SecretManager secretManager = SecretManager.instance.get(); + SecretManager secretManager = SecretManagerProvider.instance.get(); if (accessToken!=null) { JWTSecret jwtSecret = new JWTSecret(accessToken); @@ -94,7 +95,7 @@ public class RequestContextRetriever extends RequestHandler { @Override public void handleResponse(ResponseEvent e) { log.debug("resetting all the Thread local for this call."); - SecretManager.instance.get().reset(); + SecretManagerProvider.instance.get().reset(); } } From b46715dc05d58c7df7b1e564c740eaf10423cdf5 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Mon, 28 Feb 2022 16:56:56 +0100 Subject: [PATCH 05/49] Added missing reset --- .../handlers/application/request/RequestContextRetriever.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index 5860b5b..3565e7a 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -59,6 +59,7 @@ public class RequestContextRetriever extends RequestHandler { } } + SecretManagerProvider.instance.reset(); SecretManager secretManager = SecretManagerProvider.instance.get(); if (accessToken!=null) { @@ -95,7 +96,7 @@ public class RequestContextRetriever extends RequestHandler { @Override public void handleResponse(ResponseEvent e) { log.debug("resetting all the Thread local for this call."); - SecretManagerProvider.instance.get().reset(); + SecretManagerProvider.instance.reset(); } } From baab05f015184c1e199e7238e8f54faac3aa91c1 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Mon, 28 Feb 2022 17:07:57 +0100 Subject: [PATCH 06/49] fixing code --- .../application/request/RequestContextRetriever.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index 3565e7a..3ef9060 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -58,9 +58,9 @@ public class RequestContextRetriever extends RequestHandler { retrievedUser = splitAuth[0]; } } - - SecretManagerProvider.instance.reset(); - SecretManager secretManager = SecretManagerProvider.instance.get(); + + SecretManager secretManager = new SecretManager(); + SecretManagerProvider.instance.set(secretManager); if (accessToken!=null) { JWTSecret jwtSecret = new JWTSecret(accessToken); From 635036bce1145d7307fa5e48bb7892a7b0146d0b Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 11 Mar 2022 11:37:32 +0100 Subject: [PATCH 07/49] Added Linux distribution version refs #22933 --- CHANGELOG.md | 3 +- .../lifecycle/LinuxDistributionInfo.java | 93 +++++++++++++++++++ .../container/lifecycle/ProfileBuilder.java | 9 ++ 3 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java diff --git a/CHANGELOG.md b/CHANGELOG.md index ebfd6dd..54edb2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,8 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v3.2.0-SNAPSHOT] -- Added SecretManager thread local from authorization-utils [#22871] +- Added SecretManagerProvider thread local from authorization-utils [#22871] +- Added Linux distribution version [#22933] ## [v3.1.2-SNAPSHOT] - 2022-01-19 diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java new file mode 100644 index 0000000..8fe8bc2 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java @@ -0,0 +1,93 @@ +package org.gcube.smartgears.handlers.container.lifecycle; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.HashMap; +import java.util.Map; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Luca Frosini (ISTI-CNR) + */ +public class LinuxDistributionInfo { + + private static final Logger logger = LoggerFactory.getLogger(LinuxDistributionInfo.class); + + public static final String LSB_RELEASE_COMMAND = "lsb_release -a"; + public static final String OS_RELEASE_FILE_PATH = "/etc/os-release"; + + protected Map info; + + protected Map getInfoViaLsbReleaseCommand() throws IOException { + logger.trace("Going to exec {}", LSB_RELEASE_COMMAND); + Process process = Runtime.getRuntime().exec(LSB_RELEASE_COMMAND); + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); + Map map = parseBufferedReader(bufferedReader); + bufferedReader.close(); + return map; + } + + private Map parseBufferedReader(BufferedReader bufferedReader) throws IOException { + Map map = new HashMap<>(); + String line = ""; + while ((line = bufferedReader.readLine()) != null) { + String[] nameValue = parseLine(line); + map.put(nameValue[0], nameValue[1]); + } + return map; + } + + private String[] parseLine(String line) { + String[] splitted = line.split("="); + if (splitted.length < 2) { + splitted = line.split(":"); + } + String[] ret = new String[2]; + ret[0] = splitted[0].trim(); + ret[1] = splitted[1].trim().replace("\"", ""); + return ret; + } + + private Map getInfoViaFile(File file) throws IOException { + logger.trace("Going to read file {}", file.getAbsolutePath()); + BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); + Map map = parseBufferedReader(bufferedReader); + bufferedReader.close(); + return map; + + } + + protected Map getInfoViaOsReleaseFile() throws IOException { + File osReleaseFile = new File(OS_RELEASE_FILE_PATH); + return getInfoViaFile(osReleaseFile); + } + + private Map retriveInfo() { + try { + return getInfoViaLsbReleaseCommand(); + } catch (IOException e) { + + } + + try { + return getInfoViaOsReleaseFile(); + }catch (IOException e) { + + } + + return null; + } + + public Map getInfo() { + if (info == null) { + info = retriveInfo(); + } + return info; + } + +} diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java index 05c5ec6..3f1ac67 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java @@ -282,6 +282,15 @@ public class ProfileBuilder { */ + String osVersion = System.getProperty("os.name"); + if(osVersion.compareToIgnoreCase("Linux")==0) { + LinuxDistributionInfo linuxDistributionInfo = new LinuxDistributionInfo(); + Map info = linuxDistributionInfo.getInfo(); + for(String key : info.keySet()) { + variables.add().keyAndValue(key, info.get(key)); + } + } + variables.add().keyAndValue("Java", System.getProperty("java.version")); SmartGearsConfiguration config = ProviderFactory.provider().smartgearsConfiguration(); From 515891e0835013e4132b1b2f460c48023cf50867 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Fri, 11 Mar 2022 18:05:57 +0100 Subject: [PATCH 08/49] Merging patch of version 3.1.2 --- CHANGELOG.md | 2 +- .../application/request/RequestValidator.java | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54edb2f..c0f3212 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Added Linux distribution version [#22933] -## [v3.1.2-SNAPSHOT] - 2022-01-19 +## [v3.1.2] - 2022-01-19 - enabled policy check on smartgears - container configuration for test added diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 423eb54..648e8c6 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -12,10 +12,11 @@ import javax.xml.bind.annotation.XmlRootElement; import org.gcube.common.authorization.library.PolicyUtils; import org.gcube.common.authorization.library.policies.Policy; +import org.gcube.common.authorization.library.policies.User2ServicePolicy; +import org.gcube.common.authorization.library.policies.UserEntity; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.ServiceIdentifier; -import org.gcube.common.authorization.library.utils.Caller; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; @@ -120,18 +121,36 @@ public class RequestValidator extends RequestHandler { ServiceIdentifier serviceIdentifier = Utils.getServiceInfo(call.context()).getServiceIdentifier(); - Caller caller = AuthorizationProvider.instance.get(); + String callerId = AuthorizationProvider.instance.get().getClient().getId(); + + List policies = null; try { - List policies = authorizationService().getPolicies(scope); - for (Policy policy: policies) - if (PolicyUtils.isPolicyValidForClient(policy.getServiceAccess(), serviceIdentifier)){ - log.error("rejecting call to {} : {} is not allowed to contact the service ",context.name(), caller.getClient().getId()); - invalid_request_error.fire("rejecting call to "+context.name()+": "+caller.getClient().getId()+" is not allowed to contact the service"); - } + policies = authorizationService().getPolicies(scope); }catch (Exception e) { - log.warn("error getting policies from context {}", scope, e); + invalid_request_error.fire("error contating authorization for polices"); } + + for (Policy policy: policies) { + log.debug("policy: {}", policy.getPolicyAsString() ); + + if (PolicyUtils.isPolicyValidForClient(policy.getServiceAccess(), serviceIdentifier )) { + boolean toReject = false; + UserEntity entity = (((User2ServicePolicy) policy).getEntity()); + if (entity.getIdentifier()!=null) + toReject = entity.getIdentifier().equals(callerId); + else if (entity.getExcludes().isEmpty()) + toReject = true; + else toReject = !entity.getExcludes().contains(callerId); + if (toReject) { + log.error("rejecting call to {} : {} is not allowed to contact the service ",context.name(), callerId); + RequestError.request_not_authorized_error.fire("rejecting call to "+context.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() ); + } + } + + } + } + } From cf3c13495333ab0759976c9a323354b3409110db Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Thu, 17 Mar 2022 17:17:15 +0100 Subject: [PATCH 09/49] moving smartgears to a .ini Configuration file type --- .gitignore | 1 + CHANGELOG.md | 6 + pom.xml | 10 +- .../java/org/gcube/smartgears/Constants.java | 2 +- .../configuration/ProxyAddress.java | 42 ++ .../application/ApplicationConfiguration.java | 40 +- .../BridgedApplicationConfiguration.java | 43 +- .../DefaultApplicationConfiguration.java | 56 +- .../application/ProxyAddress.java | 97 ---- .../container/BaseConfiguration.java | 101 ++++ .../container/ContainerConfiguration.java | 534 ++++++------------ .../configuration/container/Site.java | 96 +--- .../application/ApplicationContext.java | 4 +- .../DefaultApplicationContext.java | 4 +- .../context/container/ContainerContext.java | 4 +- .../container/DefaultContainerContext.java | 7 +- .../application/lifecycle/ProfileBuilder.java | 6 +- .../lifecycle/ProfilePublisherImpl.java | 76 +-- .../request/RequestAccounting.java | 10 +- .../application/request/RequestValidator.java | 32 +- .../container/lifecycle/ProfileBuilder.java | 4 +- .../managers/ApplicationManager.java | 62 -- .../smartgears/managers/ContainerManager.java | 9 +- .../smartgears/managers/ContextEvents.java | 7 +- .../persistence/DefaultPersistence.java | 96 ---- .../persistence/LocalPersistence.java | 65 +++ ...ersistence.java => PersistenceWriter.java} | 8 +- .../smartgears/provider/DefaultProvider.java | 1 - .../gcube/smartgears/provider/Provider.java | 3 +- .../security/AuthorizationProvider.java | 10 + .../smartgears/security/Credentials.java | 5 + .../DefaultAuthorizationProvider.java | 14 + .../security/SimpleCredentials.java | 67 +++ src/test/java/app/SomeApp.java | 27 +- .../test/application/ConfigurationTest.java | 6 +- .../test/container/ConfigurationTest.java | 76 +-- .../test/container/PersistenceWriterTest.java | 32 ++ src/test/java/utils/TestUtils.java | 30 - src/test/resources/test-configuration.ini | 41 ++ 39 files changed, 732 insertions(+), 1002 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java delete mode 100644 src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java create mode 100644 src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java delete mode 100644 src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java create mode 100644 src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java rename src/main/java/org/gcube/smartgears/persistence/{Persistence.java => PersistenceWriter.java} (65%) create mode 100644 src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java create mode 100644 src/main/java/org/gcube/smartgears/security/Credentials.java create mode 100644 src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java create mode 100644 src/main/java/org/gcube/smartgears/security/SimpleCredentials.java create mode 100644 src/test/java/test/container/PersistenceWriterTest.java create mode 100644 src/test/resources/test-configuration.ini diff --git a/.gitignore b/.gitignore index 4110018..476f58e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ /target/ /.classpath /bin/ +/bin/ diff --git a/CHANGELOG.md b/CHANGELOG.md index c0f3212..b35f0ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm # Changelog for Common Smartgears + +## [v4.0.0-SNAPSHOT] + + + + ## [v3.2.0-SNAPSHOT] - Added SecretManagerProvider thread local from authorization-utils [#22871] diff --git a/pom.xml b/pom.xml index 39ef440..fcc1b7c 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ org.gcube.core common-smartgears - 3.2.0-SNAPSHOT + 4.0.0-SNAPSHOT SmartGears @@ -66,7 +66,7 @@ org.gcube.common common-authorization - + org.gcube.common authorization-utils @@ -97,6 +97,12 @@ common-gcore-resources + + org.ini4j + ini4j + 0.5.4 + + org.gcube.core common-validator diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index fd4486b..e0ec805 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -28,7 +28,7 @@ public class Constants { /** * The container configuration file path, relative to the container configuration directory. */ - public static final String container_configuraton_file_path = "container.xml"; + public static final String container_configuraton_file_path = "smartgears-node.ini"; /** diff --git a/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java b/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java new file mode 100644 index 0000000..731b20c --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/ProxyAddress.java @@ -0,0 +1,42 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; + +public class ProxyAddress { + + @NotNull @NotEmpty + String protocol = "http"; + + @NotNull @NotEmpty + String hostname; + + @NotNull + Integer port; + + public String getProtocol() { + return protocol; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public String getHostname() { + return hostname; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public Integer getPort() { + return port; + } + + public void setPort(Integer port) { + this.port = port; + } + + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index c7e1257..cbc85d6 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -2,8 +2,8 @@ package org.gcube.smartgears.configuration.application; import java.util.Set; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.configuration.ProxyAddress; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * The configuration of the application. @@ -13,15 +13,7 @@ import org.gcube.smartgears.persistence.Persistence; */ public interface ApplicationConfiguration { - - /** - * Returns the management mode of the application. - * @return the management mode - */ - Mode mode(); - - - + /** * Returns the context path of the application * @return the context path @@ -37,14 +29,7 @@ public interface ApplicationConfiguration { */ ApplicationConfiguration context(String context); - /** - * Sets the management mode of this application. - * @param the management mode - * @return this configuration - */ - ApplicationConfiguration mode(Mode mode); - - + /** * Returns the name of the application. * @return the name @@ -102,25 +87,12 @@ public interface ApplicationConfiguration { ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress); - /** - * Returns the tokens in which the application operates when it first starts. - * @return the tokens - */ - Set startTokens(); - - /** - * Sets the tokens in which the application operates when it first starts. - * @param scopes the scopes - * @return this configuration - */ - ApplicationConfiguration startTokens(Set tokens); - /** * Returns the persistence manager of the application. * @return the manager */ - Persistence persistence(); + PersistenceWriter persistence(); /** @@ -141,7 +113,7 @@ public interface ApplicationConfiguration { * @param manager the manager * @return this configuration */ - ApplicationConfiguration persistence(Persistence manager); + ApplicationConfiguration persistence(PersistenceWriter manager); /** diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java index caa3de1..7ab9517 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java @@ -1,14 +1,10 @@ package org.gcube.smartgears.configuration.application; -import static org.gcube.smartgears.configuration.Mode.offline; - -import java.io.File; import java.util.Set; -import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.persistence.DefaultPersistence; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.PersistenceWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -21,25 +17,18 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration private static Logger log = LoggerFactory.getLogger(ApplicationConfiguration.class); - private final ContainerConfiguration container; private final ApplicationConfiguration application; public BridgedApplicationConfiguration(ContainerConfiguration container, ApplicationConfiguration config) { - this.container=container; this.application=config; if (application.persistence()==null) { - String location = container.persistence().location()+"/"+application.name(); - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); + application.persistence(container.persistence()); - application.persistence(new DefaultPersistence(location)); - - log.trace("setting persistence location for {} @ {}",application.name(), dir.getAbsolutePath()); + log.trace("setting persistence location for {} the same as the container persistence",application.name()); } } @@ -47,10 +36,6 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration public ApplicationConfiguration inner() { return application; } - - public Mode mode() { - return container.mode()==offline?offline:application.mode(); - } @Override public String context() { @@ -98,17 +83,14 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration return application.description(description); } - public Persistence persistence() { + public PersistenceWriter persistence() { return application.persistence(); } - public ApplicationConfiguration persistence(Persistence manager) { + public ApplicationConfiguration persistence(PersistenceWriter manager) { return application.persistence(manager); } - public ApplicationConfiguration mode(Mode mode) { - return application.mode(mode); - } public void validate() { @@ -130,18 +112,7 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration public void merge(ApplicationConfiguration config) { application.merge(config); } - - - @Override - public Set startTokens() { - return application.startTokens(); - } - - @Override - public ApplicationConfiguration startTokens(Set tokens) { - return application.startTokens(tokens); - } - + @Override public boolean proxied() { diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java index a4fe514..4c34ee8 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java @@ -7,20 +7,17 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; -import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlTransient; import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotNull; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.persistence.DefaultPersistence; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.configuration.ProxyAddress; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * The configuration of a managed app. @@ -34,11 +31,6 @@ import org.gcube.smartgears.persistence.Persistence; @XmlRootElement(name="application") public class DefaultApplicationConfiguration implements ApplicationConfiguration { - - @XmlAttribute - private Mode mode = Mode.online; - - @XmlAttribute(name="context") String context; @XmlElement(name="name" , required=true) @@ -52,14 +44,10 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElement(name="version", required=true) @NotNull String version; - - @XmlTransient - Set tokens = new HashSet(); @XmlElement(name="description") String description=""; - @XmlElementRef @IsValid ProxyAddress proxyAddress; @@ -68,10 +56,10 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElementRef Set includes= new LinkedHashSet(); - - @XmlElementRef(type=DefaultPersistence.class) + + @NotNull @IsValid - private Persistence persistenceManager; + private PersistenceWriter persistenceManager; @Override public Set excludes() { @@ -85,12 +73,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration } public DefaultApplicationConfiguration() {} - - @Override - public Mode mode() { - return mode; - } - + @Override public String name() { return name; @@ -152,16 +135,6 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration return this; } - @Override - public Set startTokens() { - return tokens; - } - - @Override - public ApplicationConfiguration startTokens(Set tokens) { - this.tokens.addAll(tokens); - return this; - } @Override public String description() { @@ -180,12 +153,12 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration } @Override - public Persistence persistence() { + public PersistenceWriter persistence() { return persistenceManager; } @Override - public ApplicationConfiguration persistence(Persistence manager) { + public ApplicationConfiguration persistence(PersistenceWriter manager) { this.persistenceManager=manager; return this; } @@ -196,12 +169,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration return this; } - @Override - public ApplicationConfiguration mode(Mode mode) { - this.mode=mode; - return this; - } - + @Override public void validate() { @@ -223,13 +191,9 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @Override public void merge(ApplicationConfiguration config) { - - mode(config.mode()); - + if (config.persistence()!=null) persistence(config.persistence()); - - //scopes.addAll(config.startScopes()); } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java b/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java deleted file mode 100644 index ae9bb97..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/ProxyAddress.java +++ /dev/null @@ -1,97 +0,0 @@ -package org.gcube.smartgears.configuration.application; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.validator.annotations.NotNull; - -@XmlRootElement(name="proxy") -public class ProxyAddress { - - - @XmlAttribute - String protocol = "http"; - - @XmlElement - @NotNull - String hostname; - - @XmlElement - Integer port; - - public String hostname() { - return hostname; - } - - public ProxyAddress hostname(String hostname) { - this.hostname = hostname; - return this; - } - - public Integer port() { - return port; - } - - public ProxyAddress port(int port) { - this.port = port; - return this; - } - - public String protocol() { - return protocol; - } - - public ProxyAddress protocol(String protocol) { - this.protocol = protocol; - return this; - } - - - @Override - public String toString() { - return "ProxyAddress [protocol=" + protocol + ", hostname=" + hostname + ", port=" + port + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((hostname == null) ? 0 : hostname.hashCode()); - result = prime * result + ((port == null) ? 0 : port.hashCode()); - result = prime * result + ((protocol == null) ? 0 : protocol.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ProxyAddress other = (ProxyAddress) obj; - if (hostname == null) { - if (other.hostname != null) - return false; - } else if (!hostname.equals(other.hostname)) - return false; - if (port == null) { - if (other.port != null) - return false; - } else if (!port.equals(other.port)) - return false; - if (protocol == null) { - if (other.protocol != null) - return false; - } else if (!protocol.equals(other.protocol)) - return false; - return true; - } - - - - - -} diff --git a/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java new file mode 100644 index 0000000..9fdcb45 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java @@ -0,0 +1,101 @@ +package org.gcube.smartgears.configuration.container; + +import static org.gcube.smartgears.Constants.default_container_publication_frequency_in_seconds; + +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.Mode; + +public class BaseConfiguration { + + + Mode mode = Mode.online; + + @NotNull @NotEmpty + String hostname; + + @NotNull + Integer port; + + @NotNull @NotEmpty + String protocol="http"; + + boolean authorizeChildrenContext = false; + + @NotNull @NotEmpty + String infrastructure; + + long publicationFrequencyInSeconds = default_container_publication_frequency_in_seconds; + + public Mode getMode() { + return mode; + } + + public String getHostname() { + return hostname; + } + + public Integer getPort() { + return port; + } + + public String getProtocol() { + return protocol; + } + + public boolean isAuthorizeChildrenContext() { + return authorizeChildrenContext; + } + + public String getInfrastructure() { + return infrastructure; + } + + + + public long getPublicationFrequencyInSeconds() { + return publicationFrequencyInSeconds; + } + + public void setPublicationFrequencyInSeconds(long publicationFrequencyInSeconds) { + this.publicationFrequencyInSeconds = publicationFrequencyInSeconds; + } + + public void setMode(Mode mode) { + this.mode = mode; + } + + public void setHostname(String hostname) { + this.hostname = hostname; + } + + public void setPort(Integer port) { + this.port = port; + } + + public void setProtocol(String protocol) { + this.protocol = protocol; + } + + public void setAuthorizeChildrenContext(boolean authorizeChildrenContext) { + this.authorizeChildrenContext = authorizeChildrenContext; + } + + public void setInfrastructure(String infrastructure) { + this.infrastructure = infrastructure; + } + + + + + @Override + public String toString() { + return "BaseConfiguration [mode=" + mode + ", hostname=" + hostname + ", port=" + port + ", protocol=" + + protocol + ", authorizeChildrenContext=" + authorizeChildrenContext + ", infrastructure=" + + infrastructure + ", publicationFrequency=" + publicationFrequencyInSeconds + + "]"; + } + + + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index f138d93..ba6dc3b 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -1,19 +1,17 @@ package org.gcube.smartgears.configuration.container; -import static org.gcube.smartgears.Constants.default_container_publication_frequency_in_seconds; -import static org.gcube.smartgears.utils.Utils.notNull; - +import java.io.File; +import java.io.InputStream; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Map.Entry; import java.util.Set; +import java.util.stream.Collectors; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlTransient; import org.gcube.common.validator.ValidationError; @@ -23,10 +21,16 @@ import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.persistence.DefaultPersistence; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.LocalPersistence; +import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; +import org.gcube.smartgears.security.Credentials; +import org.gcube.smartgears.security.DefaultAuthorizationProvider; +import org.gcube.smartgears.utils.Utils; +import org.ini4j.Ini; +import org.ini4j.Profile.Section; /** * The configuration of the container. @@ -34,78 +38,45 @@ import org.gcube.smartgears.persistence.Persistence; * @author Fabio Simeoni * @author Luca Frosini (ISTI - CNR) */ -@XmlRootElement(name="container") public class ContainerConfiguration { - - @XmlAttribute - private Mode mode = Mode.online; - - @XmlElement - @NotNull @IsValid - String hostname; - - @XmlElement - @NotNull - Integer port; - - @XmlElement(name ="authentication-endpoint") - String authenticationEnpoint = null; - - @XmlElement(name ="protocol") - @NotNull @IsValid - String protocol="http"; - - @XmlElement - boolean authorizeChildrenContext = false; - - @XmlElement - @NotNull@IsValid - String infrastructure; - @XmlElement - @NotNull @IsValid - Site site; - - @XmlElement(name="token") - @NotNull @NotEmpty - List tokens = new ArrayList(); + @NotNull @IsValid + private BaseConfiguration baseConfiguration; + + @IsValid + private Map properties = new HashMap(); + + @NotNull @IsValid + private Site site; + + @IsValid + private ProxyAddress proxy; + + @NotEmpty @NotNull + private String accountingFallbackLocation; + @XmlTransient - Set allowedContext = new HashSet(); + private Set allowedContext = new HashSet(); + + private List apps = new ArrayList(); + + + @NotNull @IsValid + private PersistenceWriter persistenceManager; + + @NotNull @IsValid + private AuthorizationProvider authorizationProvider; - @XmlElementRef(type=DefaultApplicationConfiguration.class) - List apps = new ArrayList(); - - @XmlElement(name="property") - @IsValid - List properties = new ArrayList(); - - @XmlElement(name="publication-frequency") - long publicationFrequency = default_container_publication_frequency_in_seconds; - - @XmlElementRef(type=DefaultPersistence.class) - @IsValid - private Persistence persistenceManager; - /** * Returns the management mode for the container. * @return the management mode */ public Mode mode() { - return mode; + return baseConfiguration.getMode(); } - - /** - * Sets the management mode for the container. - * @param mode the management mode - * @return this configuration - */ - public ContainerConfiguration mode(Mode mode) { - this.mode=mode; - return this; - } - + /** * Returns the application configurations included in this configuration. * @return the application configurations @@ -113,21 +84,21 @@ public class ContainerConfiguration { public List apps() { return apps; } - + /** * Returns the configuration of an application with a given context path. * @param context the context path * @return the application configuration */ public ApplicationConfiguration app(String context) { - + for (ApplicationConfiguration app : apps) if (context.equals(app.context())) return app; - + return null; } - + /** * Adds the configuration of an application to this configuration. * @param app the application configuration @@ -146,7 +117,7 @@ public class ContainerConfiguration { apps.add(app); return this; } - + /** * Returns the geographical site of the container. * @return the site @@ -155,186 +126,96 @@ public class ContainerConfiguration { return site; } - /** - * Sets the geographical site of the container. - * @param site the site - * @return this configuration - */ - public ContainerConfiguration site(Site site) { - this.site=site; - return this; - } - + /** * Returns the infrastructure in which the container is running. * @return the infrastructure */ public String infrastructure() { - return infrastructure; + return baseConfiguration.getInfrastructure(); } - /** - * Sets the infrastructure in which the container is running. - * @param infrastructure the infrastructure - * @return this configuration - */ - public ContainerConfiguration infrastructure(String infrastructure) { - this.infrastructure=infrastructure; - return this; - } - - - + /** * Returns the host name of the container. * @return the host name; */ public String hostname() { - return hostname; + return baseConfiguration.getHostname(); } - - /** - * Sets the host name of the container. - * @param name the host name - * @return this configuration - */ - public ContainerConfiguration hostname(String name) { - this.hostname=name; - return this; - } - + /** * Returns the port at which the container is listening for requests. * @return the port */ public int port() { - return port; + return baseConfiguration.getPort(); } - - + + /** * Returns the port at which the container is listening for requests. * @return the port */ public String protocol() { - return protocol; - } - - - public String authenticationEnpoint() { - return authenticationEnpoint; - } - - public ContainerConfiguration authenticationEnpoint(String endpoint) { - this.authenticationEnpoint = endpoint; - return this; + return baseConfiguration.getProtocol(); } - /** - * Sets the port at which the container is listening for requests. - * @param port the port - * @return this configuration - */ - public ContainerConfiguration port(int port) { - this.port=port; - return this; - } - - public ContainerConfiguration protocol(String protocol) { - this.protocol=protocol; - return this; - } - + public boolean authorizeChildrenContext() { - return authorizeChildrenContext; - } - - public ContainerConfiguration authorizeChildrenContext(boolean authorizeChildrenContext) { - this.authorizeChildrenContext = authorizeChildrenContext; - return this; + return baseConfiguration.isAuthorizeChildrenContext(); } /** - * Returns the VOs in which the container initially operates. - * @return the VOs + * Returns the credentials. + * @return the credentials */ - public List startTokens() { - return tokens; + public AuthorizationProvider authorizationProvider() { + return authorizationProvider; } /** - * Sets the VOs in which the container initially operates. - * @param vos the VOs - * @return this configuration + * Returns the proxy of the container. + * @return the proxy */ - public ContainerConfiguration startTokens(List tokens) { - - notNull("start Tokens",tokens); - - this.tokens = tokens; - - return this; + public ProxyAddress proxy() { + return proxy; } - + + /** * Returns the persistence manager of the container. * @return the manager */ - public Persistence persistence() { + public PersistenceWriter persistence() { return persistenceManager; } /** - * Sets the persistence manager of the container. - * @param manager the manager - * @return this configuration + * Returns the persistence manager of the container. + * @return the manager */ - public ContainerConfiguration persistence(Persistence manager) { - this.persistenceManager=manager; - return this; + public String accountingFallbackLocation() { + return accountingFallbackLocation; } - + /** * Returns the configuration properties of the container. * @return the properties */ public Map properties() { - Map map = new HashMap(); - for (Property prop : properties) - map.put(prop.name, prop.value); - return map; + return Collections.unmodifiableMap(properties); } - /** - * Adds a configuration property to the container. - * @param the name of the property - * @param the value of the property - * @return this configuration - */ - public ContainerConfiguration property(String name, String value) { - properties.add(new Property(name, value)); - return this; - } - /** * Returns the publication frequency for the container's profile. * @return the frquency; */ public long publicationFrequency() { - return publicationFrequency; + return baseConfiguration.getPublicationFrequencyInSeconds(); } - - /** - * Sets the publication frequency for the container's profile. - * @param frequency the frequency - * @return this configuration - */ - public ContainerConfiguration publicationFrequency(long frequency) { - this.publicationFrequency=frequency; - return this; - } - - + + public Set allowedContexts() { return allowedContext; } @@ -353,7 +234,7 @@ public class ContainerConfiguration { List msgs = new ArrayList(); Validator validator = ValidatorFactory.validator(); - + for (ValidationError error : validator.validate(this)) msgs.add(error.toString()); @@ -362,159 +243,116 @@ public class ContainerConfiguration { } + public static ContainerConfiguration load(InputStream stream) { + try { + Ini configurator = new Ini(stream); + ContainerConfiguration conf = new ContainerConfiguration(); + + Section nodeSection = configurator.get("node"); + if (nodeSection != null ) { + BaseConfiguration nodeConf = new BaseConfiguration(); + nodeSection.to(nodeConf); + conf.baseConfiguration = nodeConf; + } + + Section propertiesSection = configurator.get("properties"); + if (propertiesSection!=null) + conf.properties = propertiesSection.entrySet().stream() + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + + Section siteSection = configurator.get("site"); + if (siteSection != null) { + Site siteConf = new Site(); + siteSection.to(siteConf); + conf.site = siteConf; + } + + initAuthorizationPart(configurator, conf); + + initPersistencePart(configurator, conf); + + initProxyPart(configurator, conf); + + + //TODO: find a solution for this shit + String location = Utils.home()+"/state"; + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + conf.accountingFallbackLocation = location; + // END Shit + + return conf; + }catch (Exception e) { + throw new RuntimeException(e); + } + } + + private static void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section proxySection = configurator.get("proxy"); + if (proxySection != null) { + ProxyAddress proxyConf = new ProxyAddress(); + proxySection.to(proxyConf); + conf.proxy = proxyConf; + } + } + private static void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section persistenceSection = configurator.get("persistence"); + if (persistenceSection != null) { + String type = persistenceSection.get("class"); + if (type ==null) + throw new Exception("ini file error: type not found in \"persistence\" section"); + PersistenceWriter persistenceWriter; + try { + Object persistenceImpl = Class.forName(type).newInstance(); + persistenceWriter = PersistenceWriter.class.cast(persistenceImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e); + } + persistenceSection.to(persistenceWriter); + conf.persistenceManager = persistenceWriter; + } else { + String location = Utils.home()+"/state"; + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + conf.persistenceManager = new LocalPersistence(location); + } + } - static class Property { - - @XmlAttribute @NotNull - String name; - - @XmlAttribute @NotNull - String value; - - Property() {} - - Property(String key, String value) { - this.name=key; - this.value=value; + private static void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section authorizationSection = configurator.get("authorization"); + if (authorizationSection != null) { + + String provider = authorizationSection.get("provider"); + AuthorizationProvider authProvider; + if (provider!=null) { + try { + Object authProviderImpl = Class.forName(provider).newInstance(); + authProvider = AuthorizationProvider.class.cast(authProviderImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid provider type in \"authorization\" section", e); + } + } else + authProvider = new DefaultAuthorizationProvider(); + + + String type = authorizationSection.get("credentials.class"); + if (type ==null) + throw new Exception("ini file error: credentials type not found in \"authorization\" section"); + Credentials credentials; + try { + Object credentialsImpl = Class.forName(type).newInstance(); + credentials = Credentials.class.cast(credentialsImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e); + } + authorizationSection.to(credentials, "credentials."); + + authProvider.connect(credentials); + + conf.authorizationProvider = authProvider; } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((name == null) ? 0 : name.hashCode()); - result = prime * result + ((value == null) ? 0 : value.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - Property other = (Property) obj; - if (name == null) { - if (other.name != null) - return false; - } else if (!name.equals(other.name)) - return false; - if (value == null) { - if (other.value != null) - return false; - } else if (!value.equals(other.value)) - return false; - return true; - } - } - - - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((allowedContext == null) ? 0 : allowedContext.hashCode()); - result = prime * result + ((apps == null) ? 0 : apps.hashCode()); - result = prime * result + ((authenticationEnpoint == null) ? 0 : authenticationEnpoint.hashCode()); - result = prime * result + (authorizeChildrenContext ? 1231 : 1237); - result = prime * result + ((hostname == null) ? 0 : hostname.hashCode()); - result = prime * result + ((infrastructure == null) ? 0 : infrastructure.hashCode()); - result = prime * result + ((mode == null) ? 0 : mode.hashCode()); - result = prime * result + ((persistenceManager == null) ? 0 : persistenceManager.hashCode()); - result = prime * result + ((port == null) ? 0 : port.hashCode()); - result = prime * result + ((properties == null) ? 0 : properties.hashCode()); - result = prime * result + ((protocol == null) ? 0 : protocol.hashCode()); - result = prime * result + (int) (publicationFrequency ^ (publicationFrequency >>> 32)); - result = prime * result + ((site == null) ? 0 : site.hashCode()); - result = prime * result + ((tokens == null) ? 0 : tokens.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - ContainerConfiguration other = (ContainerConfiguration) obj; - if (allowedContext == null) { - if (other.allowedContext != null) - return false; - } else if (!allowedContext.equals(other.allowedContext)) - return false; - if (apps == null) { - if (other.apps != null) - return false; - } else if (!apps.equals(other.apps)) - return false; - if (authenticationEnpoint == null) { - if (other.authenticationEnpoint != null) - return false; - } else if (!authenticationEnpoint.equals(other.authenticationEnpoint)) - return false; - if (authorizeChildrenContext != other.authorizeChildrenContext) - return false; - if (hostname == null) { - if (other.hostname != null) - return false; - } else if (!hostname.equals(other.hostname)) - return false; - if (infrastructure == null) { - if (other.infrastructure != null) - return false; - } else if (!infrastructure.equals(other.infrastructure)) - return false; - if (mode != other.mode) - return false; - if (persistenceManager == null) { - if (other.persistenceManager != null) - return false; - } else if (!persistenceManager.equals(other.persistenceManager)) - return false; - if (port == null) { - if (other.port != null) - return false; - } else if (!port.equals(other.port)) - return false; - if (properties == null) { - if (other.properties != null) - return false; - } else if (!properties.equals(other.properties)) - return false; - if (protocol == null) { - if (other.protocol != null) - return false; - } else if (!protocol.equals(other.protocol)) - return false; - if (publicationFrequency != other.publicationFrequency) - return false; - if (site == null) { - if (other.site != null) - return false; - } else if (!site.equals(other.site)) - return false; - if (tokens == null) { - if (other.tokens != null) - return false; - } else if (!tokens.equals(other.tokens)) - return false; - return true; - } - - @Override - public String toString() { - return "ContainerConfiguration [mode=" + mode + ", hostname=" + hostname + ", port=" + port + ", authenticationEnpoint=" + authenticationEnpoint + ", protocol=" + protocol - + ", authorizeChildrenContext=" + authorizeChildrenContext + ", infrastructure=" + infrastructure - + ", site=" + site + ", tokens=" + tokens + ", allowedContext=" + allowedContext + ", apps=" + apps - + ", properties=" + properties + ", publicationFrequency=" + publicationFrequency - + ", persistenceManager=" + persistenceManager + "]"; - } - } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/container/Site.java b/src/main/java/org/gcube/smartgears/configuration/container/Site.java index cc41f4f..2c22935 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/Site.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/Site.java @@ -1,8 +1,5 @@ package org.gcube.smartgears.configuration.container; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.validator.annotations.NotNull; /** @@ -11,97 +8,52 @@ import org.gcube.common.validator.annotations.NotNull; * @author Fabio Simeoni * */ -@XmlRootElement(name="site") public class Site { - @XmlElement @NotNull String country; - @XmlElement @NotNull String location; - @XmlElement @NotNull String latitude; - @XmlElement @NotNull String longitude; - /** - * Returns the country. - * @return the country - */ - public String country() { + + + public String getCountry() { return country; } - /** - * Sets the country. - * @param the country - * @return this configuration - */ - public Site country(String country) { - this.country=country; - return this; - } - - - /** - * Returns the latitude. - * @return the latitude - */ - public String latitude() { - return latitude; + public void setCountry(String country) { + this.country = country; } - /** - * Sets the latitude. - * @param the latitude - * @return this configuration - */ - public Site latitude(String latitude) { - this.latitude=latitude; - return this; - } - - - /** - * Returns the longitude. - * @return the longitude - */ - public String longitude() { - return longitude; - } - - /** - * Sets the longitude. - * @param the longitude - * @return this configuration - */ - public Site longitude(String longitude) { - this.longitude=longitude; - return this; - } - - /** - * Returns the location. - * @return the location - */ - public String location() { + public String getLocation() { return location; } - /** - * Sets the location. - * @param the location - * @return this location - */ - public Site location(String location) { - this.location=location; - return this; + public void setLocation(String location) { + this.location = location; + } + + public String getLatitude() { + return latitude; + } + + public void setLatitude(String latitude) { + this.latitude = latitude; + } + + public String getLongitude() { + return longitude; + } + + public void setLongitude(String longitude) { + this.longitude = longitude; } @Override diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java index 033cb34..b24640a 100644 --- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java @@ -7,7 +7,7 @@ import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * The management context of an application. @@ -56,7 +56,7 @@ public interface ApplicationContext { * * @return the manager */ - Persistence persistence(); + PersistenceWriter persistence(); /** * Returns the servlet context of the application. diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 96f2b3a..fbe0328 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -10,7 +10,7 @@ import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * Default {@link ApplicationContext} implementation. @@ -96,7 +96,7 @@ public class DefaultApplicationContext implements ApplicationContext { } @Override - public Persistence persistence() { + public PersistenceWriter persistence() { return configuration.persistence(); } diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index 3c7ae53..6afb028 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -4,7 +4,7 @@ import org.gcube.common.events.Hub; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * The management context of the container. @@ -43,7 +43,7 @@ public interface ContainerContext { * Returns the persistence manager of the container. * @return the manager */ - Persistence persistence(); + PersistenceWriter persistence(); /** * Returns the properties of the container. diff --git a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java index 0a599f7..7d5fe14 100644 --- a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java @@ -1,12 +1,13 @@ package org.gcube.smartgears.context.container; -import static org.gcube.smartgears.Constants.*; +import static org.gcube.smartgears.Constants.container_profile_property; + import org.gcube.common.events.Hub; import org.gcube.common.resources.gcore.HostingNode; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; -import org.gcube.smartgears.persistence.Persistence; +import org.gcube.smartgears.persistence.PersistenceWriter; /** * Default {@link ContainerContext} implementation. @@ -62,7 +63,7 @@ public class DefaultContainerContext implements ContainerContext { } @Override - public Persistence persistence() { + public PersistenceWriter persistence() { return configuration.persistence(); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java index da9c635..2caf451 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java @@ -48,10 +48,10 @@ public class ProfileBuilder { String baseAddress; if (configuration.proxied()){ - String protocol = configuration.proxyAddress().protocol(); - String port = configuration.proxyAddress().port()!=null?":"+configuration.proxyAddress().port():""; + String protocol = configuration.proxyAddress().getProtocol(); + String port = configuration.proxyAddress().getPort()!=null?":"+configuration.proxyAddress().getPort():""; - baseAddress=String.format("%s://%s%s%s", protocol , configuration.proxyAddress().hostname(), port,context.application().getContextPath()); + baseAddress=String.format("%s://%s%s%s", protocol , configuration.proxyAddress().getHostname(), port,context.application().getContextPath()); } else { String protocol = container.protocol(); int port = container.port(); diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java index 54f9930..269a99e 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java @@ -8,14 +8,15 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.resources.gcore.GCoreEndpoint; +import org.gcube.common.scope.api.ScopeProvider; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.ProfilePublisher; import org.gcube.smartgears.provider.ProviderFactory; +import org.gcube.smartgears.security.AuthorizationProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +38,7 @@ public class ProfilePublisherImpl implements ProfilePublisher { private final ApplicationContext context; - private AuthorizationProxy authProxy ; + private AuthorizationProvider authProxy ; /** * Creates an instance for a given application. @@ -46,7 +47,7 @@ public class ProfilePublisherImpl implements ProfilePublisher { public ProfilePublisherImpl(ApplicationContext context) { this.context = context; this.publisher=ProviderFactory.provider().publisherFor(context); - this.authProxy = ProviderFactory.provider().authorizationProxy(); + this.authProxy = context.container().configuration().authorizationProvider(); } /** @@ -54,9 +55,9 @@ public class ProfilePublisherImpl implements ProfilePublisher { * @param scopes the scopes */ @Override - public void addTo(Collection tokens) { + public void addTo(Collection contexts) { - notEmpty("tokens",tokens); + notEmpty("tokens",contexts); GCoreEndpoint profile = context.profile(GCoreEndpoint.class); @@ -87,16 +88,19 @@ public class ProfilePublisherImpl implements ProfilePublisher { log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)tokens.toArray()[0]); + if (previousToken!=null) + SecurityTokenProvider.instance.reset();; if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.create(profile, resolveScopesFromTokens(tokens)); + ScopeProvider.instance.set(contexts.stream().findFirst().get()); + profile = publisher.create(profile, new ArrayList(contexts)); } catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } @@ -106,7 +110,7 @@ public class ProfilePublisherImpl implements ProfilePublisher { @Override public void addToAll() { - this.addTo(context.configuration().startTokens()); + this.addTo(context.configuration().allowedContexts()); } @@ -115,33 +119,16 @@ public class ProfilePublisherImpl implements ProfilePublisher { GCoreEndpoint profile = context.profile(GCoreEndpoint.class); - - /* TODO: reintroduce it when scope will be removed - String previousToken = SecurityTokenProvider.instance.get(); - try { - - for (String token: context.configuration().startTokens()){ - SecurityTokenProvider.instance.set(token); - profile = publisher.update(profile); - SecurityTokenProvider.instance.reset(); - } - - } - catch (Exception e) { - rethrowUnchecked(e); - } finally{ - SecurityTokenProvider.instance.set(previousToken); - } - */ ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]); + if (previousToken!=null) + SecurityTokenProvider.instance.reset(); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); @@ -151,6 +138,7 @@ public class ProfilePublisherImpl implements ProfilePublisher { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } @@ -164,46 +152,28 @@ public class ProfilePublisherImpl implements ProfilePublisher { * @param scopes the scopes */ @Override - public void removeFrom(Collection tokens) { + public void removeFrom(Collection contexts) { GCoreEndpoint profile = context.profile(GCoreEndpoint.class); - /* TODO: reintroduce it when scope will be removed - String previousToken = SecurityTokenProvider.instance.get(); - try { - - for (String token: tokens){ - SecurityTokenProvider.instance.set(token); - profile = publisher.remove(profile); - SecurityTokenProvider.instance.reset(); - } - - } - catch (Exception e) { - - rethrowUnchecked(e); - - } finally{ - SecurityTokenProvider.instance.set(previousToken); - } - */ - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); log.debug("using context {}",contextCL.getClass().getSimpleName()); String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)tokens.toArray()[0]); + if (previousToken!=null) + SecurityTokenProvider.instance.reset(); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.remove(profile, resolveScopesFromTokens(tokens)); + profile = publisher.remove(profile, contexts); } catch (Exception e) { rethrowUnchecked(e); } finally{ SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 61f7b33..97dff80 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -8,8 +8,8 @@ import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; @@ -46,7 +46,7 @@ public class RequestAccounting extends RequestHandler { calledMethod= e.request().getMethod()+" "+calledMethod; } InnerMethodName.instance.set(calledMethod); - String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN"; + String caller = SecretManagerProvider.instance.get().getUser().getUsername(); startCallThreadLocal.set(System.currentTimeMillis()); log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), @@ -65,8 +65,8 @@ public class RequestAccounting extends RequestHandler { resetScope = true; } - String caller = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getClient().getId(): "UNKNOWN"; - String callerQualifier = AuthorizationProvider.instance.get()!=null? AuthorizationProvider.instance.get().getTokenQualifier(): "UNKNOWN"; + String caller = SecretManagerProvider.instance.get().getUser().getUsername(); + String callerQualifier = "UNKNOWN"; //retieves caller Ip when there is a proxy String callerIp = e.request().getHeader("x-forwarded-for"); if(callerIp==null) @@ -87,7 +87,7 @@ public class RequestAccounting extends RequestHandler { } void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){ - AccountingPersistenceFactory.setFallbackLocation(context.container().persistence().location()); + AccountingPersistenceFactory.setFallbackLocation(context.container().configuration().accountingFallbackLocation()); AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); try{ diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 648e8c6..b894db1 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -14,9 +14,9 @@ import org.gcube.common.authorization.library.PolicyUtils; import org.gcube.common.authorization.library.policies.Policy; import org.gcube.common.authorization.library.policies.User2ServicePolicy; import org.gcube.common.authorization.library.policies.UserEntity; -import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.library.provider.ServiceIdentifier; +import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; @@ -39,7 +39,7 @@ public class RequestValidator extends RequestHandler { private static Logger log = LoggerFactory.getLogger(RequestValidator.class); - private ApplicationContext context; + private ApplicationContext appContext; @Override public String getName() { @@ -51,13 +51,13 @@ public class RequestValidator extends RequestHandler { log.trace("executing request validator ON REQUEST"); - context = call.context(); + appContext = call.context(); validateAgainstLifecycle(call); rejectUnauthorizedCalls(call); - if (context.container().configuration().mode()!=Mode.offline) { + if (appContext.container().configuration().mode()!=Mode.offline) { validateScopeCall(); validatePolicy(ScopeProvider.instance.get(), call); } @@ -66,7 +66,7 @@ public class RequestValidator extends RequestHandler { private void validateAgainstLifecycle(RequestEvent call) { - switch(context.lifecycle().state()) { + switch(appContext.lifecycle().state()) { case stopped : application_unavailable_error.fire(); break; @@ -86,28 +86,28 @@ public class RequestValidator extends RequestHandler { String scope = ScopeProvider.instance.get(); if (scope == null) { - log.warn("rejecting unscoped call to {}",context.name()); + log.warn("rejecting unscoped call to {}",appContext.name()); invalid_request_error.fire("call is unscoped"); } ScopeBean bean = new ScopeBean(scope); - ContainerConfiguration conf = context.container().configuration(); + ContainerConfiguration conf = appContext.container().configuration(); if (!conf.allowedContexts().contains(scope) && !(conf.authorizeChildrenContext() && bean.is(Type.VRE) && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) { - log.warn("rejecting call to {} in invalid context {}, allowed context are {}",context.name(),scope,context.container().configuration().allowedContexts()); - invalid_request_error.fire(context.name()+" cannot be called in scope "+scope); + log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),scope,appContext.container().configuration().allowedContexts()); + invalid_request_error.fire(appContext.name()+" cannot be called in scope "+scope); } } private void rejectUnauthorizedCalls(RequestEvent call){ String token = SecurityTokenProvider.instance.get(); - String scope = ScopeProvider.instance.get(); + String context = SecretManagerProvider.instance.get().getContext(); - if (token == null && scope==null){ - log.warn("rejecting call to {}, authorization required",context.name(),token); - RequestError.request_not_authorized_error.fire(context.name()+": authorization required"); + if (token == null && context==null){ + log.warn("rejecting call to {}, authorization required",appContext.name(),token); + RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); } } @@ -121,7 +121,7 @@ public class RequestValidator extends RequestHandler { ServiceIdentifier serviceIdentifier = Utils.getServiceInfo(call.context()).getServiceIdentifier(); - String callerId = AuthorizationProvider.instance.get().getClient().getId(); + String callerId = SecretManagerProvider.instance.get().getUser().getUsername(); List policies = null; try { @@ -142,8 +142,8 @@ public class RequestValidator extends RequestHandler { toReject = true; else toReject = !entity.getExcludes().contains(callerId); if (toReject) { - log.error("rejecting call to {} : {} is not allowed to contact the service ",context.name(), callerId); - RequestError.request_not_authorized_error.fire("rejecting call to "+context.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() ); + log.error("rejecting call to {} : {} is not allowed to contact the service ",appContext.name(), callerId); + RequestError.request_not_authorized_error.fire("rejecting call to "+appContext.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() ); } } diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java index 3f1ac67..73b6e32 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java @@ -97,7 +97,7 @@ public class ProfileBuilder { // // file system node.profile().description().localFileSystems().add().name("").type("").readOnly(false) - .root(cfg.persistence().location()); + .root("/"); return node; } @@ -192,7 +192,7 @@ public class ProfileBuilder { private long getFreeSpace() { long free = 0; try { - free = Files.getFileStore(Paths.get(context.configuration().persistence().location())).getUsableSpace()/1024; + free = context.configuration().persistence().getFreeSpace()/1024; } catch (IOException ioe) { log.warn("unable to detect the free space on the disk", ioe); } diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index 7f3e735..0ed56a8 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -23,10 +23,7 @@ import javax.servlet.ServletContextEvent; import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration; -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.events.Observes; -import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; @@ -34,14 +31,12 @@ import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.extensions.RequestExceptionBarrier; -import org.gcube.smartgears.handlers.ProfileEvents; import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.ApplicationPipeline; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; -import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -143,41 +138,6 @@ public class ApplicationManager { } - private List generateTokensForApplication(ContainerContext container){ - log.info("generating token for app {}",context.configuration().name()); - - SecurityTokenProvider.instance.set(container.configuration().startTokens().get(0)); - try { - AuthorizationProxy authProxy = provider().authorizationProxy(); - try { - return authProxy.generateServiceToken(Utils.getServiceInfo(context), container.configuration().startTokens()); - }catch (Exception e) { - log.error("error generating service token",e); - throw new RuntimeException(e); - } - } catch (Exception e) { - throw new RuntimeException("error contacting authorization service",e); - } finally{ - SecurityTokenProvider.instance.reset(); - } - - - } - - private String generateApplicationToken(String containerToken, AuthorizationProxy authProxy){ - SecurityTokenProvider.instance.set(containerToken); - try { - log.info("generating token for app {} with container token {} ",context.configuration().name(), containerToken); - return authProxy.generateServiceToken(Utils.getServiceInfo(context)); - } catch (Exception e) { - throw new RuntimeException("error contacting authorization service",e); - } finally{ - SecurityTokenProvider.instance.reset(); - } - - } - - private void saveApplicationState() { File file = context.configuration().persistence().file(profile_file_path); try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){ @@ -320,28 +280,6 @@ public class ApplicationManager { log.warn("cannot stop {} after container has stopped", context.name()); } - @Observes(value = ContextEvents.ADD_TOKEN_TO_APPLICATION, kind = critical) - void onAddToken(String containerToken) { - log.trace("event add received with token {} ",containerToken); - String appToken = generateApplicationToken(containerToken, provider().authorizationProxy()); - context.configuration().startTokens().add(appToken); - log.trace("app token created : {} ", appToken); - context.events().fire(appToken, ProfileEvents.addToContext); - context.events().fire(appToken, Constants.token_registered); - saveApplicationState(); - } - - @Observes(value = ContextEvents.REMOVE_TOKEN_FROM_APPLICATION, kind = critical) - void onRemoveToken(String containerToken) { - log.trace("event remove received with token {} ",containerToken); - String appToken = generateApplicationToken(containerToken, provider().authorizationProxy()); - context.configuration().startTokens().remove(appToken); - log.trace("app token removed : {} ", appToken); - context.events().fire(appToken, ProfileEvents.removeFromContext); - context.events().fire(appToken, Constants.token_removed); - saveApplicationState(); - } - }; context.container().events().subscribe(observer); diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 3d7a9d2..92ae6d8 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -31,6 +31,8 @@ import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; import org.gcube.smartgears.handlers.container.ContainerPipeline; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerState; +import org.gcube.smartgears.security.AuthorizationProvider; +import org.gcube.smartgears.security.Credentials; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -47,7 +49,7 @@ public class ContainerManager { public static ContainerManager instance = new ContainerManager(); - private AuthorizationProxy authProvider = provider().authorizationProxy(); + private AuthorizationProvider authProvider = provider().authorizationProxy(); private ContainerContext context; @@ -101,7 +103,6 @@ public class ContainerManager { File file = context.configuration().persistence().file(container_profile_file_path); try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){ oos.writeObject(context.id()); - oos.writeObject(context.configuration().startTokens()); }catch (Exception e) { log.error("error serializing cointainer state"); throw new RuntimeException(e); @@ -113,7 +114,9 @@ public class ContainerManager { //List tokensToRemove = new ArrayList(); context.configuration().validate(); Set foundContexts= new HashSet(); - + + Credentials credential = context.configuration().credentials(); + try { List entries = authProvider.get(context.configuration().startTokens()); diff --git a/src/main/java/org/gcube/smartgears/managers/ContextEvents.java b/src/main/java/org/gcube/smartgears/managers/ContextEvents.java index 8b771c2..224093b 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContextEvents.java +++ b/src/main/java/org/gcube/smartgears/managers/ContextEvents.java @@ -2,12 +2,9 @@ package org.gcube.smartgears.managers; public class ContextEvents { - public static final String ADD_TOKEN_TO_CONTAINER ="AddTokenToContainer"; + public static final String ADD_CONTEXT_TO_CONTAINER ="AddContextToContainer"; - public static final String ADD_TOKEN_TO_APPLICATION ="AddTokenToApplication"; + public static final String REMOVE_CONTEXT_FROM_CONTAINER ="RemoveContextFromContainer"; - public static final String REMOVE_TOKEN_FROM_CONTAINER ="RemoveTokenFromContainer"; - - public static final String REMOVE_TOKEN_FROM_APPLICATION ="RemoveTokenFromApplication"; } diff --git a/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java b/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java deleted file mode 100644 index 21dbbc3..0000000 --- a/src/main/java/org/gcube/smartgears/persistence/DefaultPersistence.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.gcube.smartgears.persistence; - - -import static org.gcube.smartgears.utils.Utils.*; - -import java.io.File; - -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.validator.annotations.NotNull; - -@XmlRootElement(name="persistence") -public class DefaultPersistence implements Persistence { - - @XmlAttribute(name="location") @NotNull - private String location; - - public DefaultPersistence() {} - - public DefaultPersistence(String location) { - - notNull("persistence location",location); - - this.location=location; - validate(); - } - - @Override - public String location() { - return location; - } - - @Override - public File writefile(String path) { - - notNull("relative path", path); - - return fileAt(new File(location, path).getAbsolutePath()).toWrite(); - } - - @Override - public File file(String path) { - - notNull("relative path", path); - - return fileAt(new File(location, path).getAbsolutePath()).toRead(); - } - - - //called after JAXB unmarshalling to purge unavailable handlers - void afterUnmarshal(Unmarshaller u, Object parent) { - - validate(); - } - - public void validate() { - - File locationDir = new File(location); - if (!(locationDir.exists() && locationDir.isDirectory() && locationDir.canRead() && locationDir.canWrite())) - throw new IllegalStateException("invalid node configuration: home "+location+" does not exist or is not a directory or cannot be accessed in read/write mode"); - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((location == null) ? 0 : location.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - DefaultPersistence other = (DefaultPersistence) obj; - if (location == null) { - if (other.location != null) - return false; - } else if (!location.equals(other.location)) - return false; - return true; - } - - @Override - public String toString() { - return "local persistence in "+location; - } - -} diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java new file mode 100644 index 0000000..9e9ca85 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java @@ -0,0 +1,65 @@ +package org.gcube.smartgears.persistence; + + +import static org.gcube.smartgears.utils.Utils.fileAt; +import static org.gcube.smartgears.utils.Utils.notNull; + +import java.io.File; + +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; + +public class LocalPersistence implements PersistenceWriter { + + @NotNull @NotEmpty + private String location; + + protected LocalPersistence() {} + + public LocalPersistence(String location) { + + notNull("persistence location",location); + + this.location=location; + + validate(); + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + + @Override + public File writefile(String path) { + + notNull("relative path", path); + + return fileAt(new File(location, path).getAbsolutePath()).toWrite(); + } + + @Override + public File file(String path) { + + notNull("relative path", path); + + return fileAt(new File(location, path).getAbsolutePath()).toRead(); + } + + void initialize(){ + + } + + public void validate() { + + File locationDir = new File(location); + if (!(locationDir.exists() && locationDir.isDirectory() && locationDir.canRead() && locationDir.canWrite())) + throw new IllegalStateException("invalid node configuration: home "+location+" does not exist or is not a directory or cannot be accessed in read/write mode"); + + } + +} diff --git a/src/main/java/org/gcube/smartgears/persistence/Persistence.java b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java similarity index 65% rename from src/main/java/org/gcube/smartgears/persistence/Persistence.java rename to src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java index 058480e..528b350 100644 --- a/src/main/java/org/gcube/smartgears/persistence/Persistence.java +++ b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java @@ -2,12 +2,12 @@ package org.gcube.smartgears.persistence; import java.io.File; -public interface Persistence { - - String location(); - +public interface PersistenceWriter { + File file(String path); File writefile(String path); + + long getFreeSpace(); } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 1466d25..0bf1e8e 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -221,7 +221,6 @@ public class DefaultProvider implements Provider { } } - // TODO we can check scopes here instead of in BridgedApplicationConfiguration constructor ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration(context.configuration(), configuration); diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index 13f538d..40f1da3 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -10,6 +10,7 @@ import org.gcube.smartgears.configuration.container.ContainerHandlers; import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.security.AuthorizationProvider; /** * Provides dependencies for container and application management. @@ -84,6 +85,6 @@ public interface Provider { * @param application the context of the application * @return the publisher implementation */ - AuthorizationProxy authorizationProxy(); + AuthorizationProvider authorizationProxy(); } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java new file mode 100644 index 0000000..13b5e86 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -0,0 +1,10 @@ +package org.gcube.smartgears.security; + +import java.util.Collection; + +public interface AuthorizationProvider { + + void connect(Credentials credentials) throws Exception; + + Collection getAllowedContexts(); +} diff --git a/src/main/java/org/gcube/smartgears/security/Credentials.java b/src/main/java/org/gcube/smartgears/security/Credentials.java new file mode 100644 index 0000000..088a338 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/Credentials.java @@ -0,0 +1,5 @@ +package org.gcube.smartgears.security; + +public interface Credentials { + +} diff --git a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java new file mode 100644 index 0000000..2645fff --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java @@ -0,0 +1,14 @@ +package org.gcube.smartgears.security; + + + +public class DefaultAuthorizationProvider implements AuthorizationProvider { + + SimpleCredentials credentials; + + @Override + public void connect(Credentials credentials) { + this.credentials = (SimpleCredentials)credentials; + } + +} diff --git a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java new file mode 100644 index 0000000..3c8a5ab --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java @@ -0,0 +1,67 @@ +package org.gcube.smartgears.security; + +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; + +public class SimpleCredentials implements Credentials{ + + @NotNull @NotEmpty + String clientID; + + @NotNull @NotEmpty + String secret; + + public String getClientID() { + return clientID; + } + + public void setClientID(String clientID) { + this.clientID = clientID; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((clientID == null) ? 0 : clientID.hashCode()); + result = prime * result + ((secret == null) ? 0 : secret.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + SimpleCredentials other = (SimpleCredentials) obj; + if (clientID == null) { + if (other.clientID != null) + return false; + } else if (!clientID.equals(other.clientID)) + return false; + if (secret == null) { + if (other.secret != null) + return false; + } else if (!secret.equals(other.secret)) + return false; + return true; + } + + @Override + public String toString() { + return "SimpleCredentials [clientID=" + clientID + ", secret=" + secret + "]"; + } + + +} diff --git a/src/test/java/app/SomeApp.java b/src/test/java/app/SomeApp.java index edc311d..aa108ad 100644 --- a/src/test/java/app/SomeApp.java +++ b/src/test/java/app/SomeApp.java @@ -10,6 +10,7 @@ import static utils.TestUtils.location; import static utils.TestUtils.servlet_name; import java.io.File; +import java.io.InputStream; import org.apache.catalina.Wrapper; import org.apache.catalina.core.StandardContext; @@ -18,13 +19,11 @@ import org.apache.commons.io.FileUtils; import org.apache.tomcat.util.scan.StandardJarScanner; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.Constants; -import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.configuration.container.Site; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.managers.ContainerManager; import org.gcube.smartgears.provider.ProviderFactory; @@ -249,8 +248,7 @@ public class SomeApp { if (clean) cleanupInstallation(); - installContainerConfiguration(); - + if (deployConfiguration) deployConfiguration(); @@ -283,7 +281,7 @@ public class SomeApp { webapp.setServlet(new TestServlet(test)); - context.container().configuration().port(port()); + //context.container().configuration().port(port()); containerConfiguration = context.container().configuration(); } @@ -343,14 +341,7 @@ public class SomeApp { } // helpers - /** - * Installs the container configuration. - */ - private void installContainerConfiguration() { - - TestUtils.serialise(containerConfiguration(),containerConfigurationFile()); - - } + /** * Includes the configuration in the application's WAR. @@ -411,17 +402,15 @@ public class SomeApp { private ApplicationConfiguration defaultConfiguration() { - return new DefaultApplicationConfiguration().mode(Mode.offline).serviceClass("test-class").name("test-app").version("1.0"); + return new DefaultApplicationConfiguration().serviceClass("test-class").name("test-app").version("1.0"); } private ContainerConfiguration defaultContainerConfiguration() { - return new ContainerConfiguration().mode(Mode.offline).hostname("localhost").port(port()).infrastructure("gcube") - .site(new Site().country("it").location("rome").latitude("41.9000").longitude("12.5000")) - .property("test-prop1","foo") - .property("test-prop2","bar") - .publicationFrequency(5); + InputStream is = SomeApp.class.getResourceAsStream("/test-configuration.ini"); + + return ContainerConfiguration.load(is); } diff --git a/src/test/java/test/application/ConfigurationTest.java b/src/test/java/test/application/ConfigurationTest.java index c9d6d81..b9b84a3 100644 --- a/src/test/java/test/application/ConfigurationTest.java +++ b/src/test/java/test/application/ConfigurationTest.java @@ -5,14 +5,13 @@ import static junit.framework.Assert.assertNotNull; import java.io.ByteArrayInputStream; -import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; import org.gcube.smartgears.configuration.application.Include; import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.persistence.DefaultPersistence; +import org.gcube.smartgears.persistence.LocalPersistence; import org.junit.Test; public class ConfigurationTest { @@ -99,14 +98,13 @@ public class ConfigurationTest { return new DefaultApplicationConfiguration() - .mode(Mode.offline) .context("ctx") .name("name") .serviceClass("class") .includes(new Include("/pathBis")) .version("version") .description("desc") - .persistence(new DefaultPersistence("target")); + .persistence(new LocalPersistence("target")); } diff --git a/src/test/java/test/container/ConfigurationTest.java b/src/test/java/test/container/ConfigurationTest.java index 0f29ef6..a20f772 100644 --- a/src/test/java/test/container/ConfigurationTest.java +++ b/src/test/java/test/container/ConfigurationTest.java @@ -1,19 +1,10 @@ package test.container; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertTrue; +import java.io.StringWriter; -import java.io.ByteArrayInputStream; -import java.util.Arrays; -import java.util.List; - -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder; -import org.gcube.smartgears.configuration.container.Site; -import org.gcube.smartgears.persistence.DefaultPersistence; +import org.ini4j.Ini; +import org.ini4j.Profile.Section; import org.junit.Test; public class ConfigurationTest { @@ -21,51 +12,30 @@ public class ConfigurationTest { @Test public void containerConfigurationBinds() throws Exception { - String appXml = "" + "name" + "class" - + "version" + "desc" + "" - + ""; - - String xml = "" - + "localhost" - + "8080" - + "gcube" - + "true " - +"token1" + "token2" + "" + appXml + "" - + "it" + "rome" + "41.9000" - + "12.5000" + "" + "" - + "" + "30" - + ""; - - ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); - - ContainerConfiguration bound = binder.bind(new ByteArrayInputStream(xml.getBytes())); - + ContainerConfiguration bound = ContainerConfiguration + .load(ConfigurationTest.class.getResourceAsStream("/test-configuration.ini")); + bound.validate(); - - List scopes = bound.startTokens(); - - assertTrue(scopes.contains("token1")); - assertTrue(scopes.contains("token2")); - - assertEquals(sampleContainerConfiguration(), bound); - + } - private ContainerConfiguration sampleContainerConfiguration() { + @Test + public void iniStore() throws Exception { + Ini ini = new Ini(); - return new ContainerConfiguration().mode(Mode.offline).hostname("localhost").port(8080).infrastructure("gcube") - .startTokens(Arrays.asList("token1", "token2")) - .site(new Site().country("it").location("rome").latitude("41.9000").longitude("12.5000")) - .property("prop1", "val1").property("prop2", "val2").publicationFrequency(30) - .app(sampleAppConfiguration()).authorizeChildrenContext(true) - .persistence(new DefaultPersistence("target")); - - } - - private ApplicationConfiguration sampleAppConfiguration() { - - return new DefaultApplicationConfiguration().mode(Mode.offline).name("name").serviceClass("class") - .version("version").description("desc").persistence(new DefaultPersistence("target")); + // lets add a section, it will create needed intermediate sections as well + ini.add("root/child/sub"); + Section rsec = ini.get("root"); + rsec.add("test", "team"); + Section csec = rsec.getChild("child"); + csec.add("testchild", "pappo"); + Section ssec = csec.getChild("sub"); + ssec.add("testSec", "pippo"); + + StringWriter sw = new StringWriter(); + ini.store(sw); + + System.out.println(sw.toString()); } } diff --git a/src/test/java/test/container/PersistenceWriterTest.java b/src/test/java/test/container/PersistenceWriterTest.java new file mode 100644 index 0000000..f593fa5 --- /dev/null +++ b/src/test/java/test/container/PersistenceWriterTest.java @@ -0,0 +1,32 @@ +package test.container; + +import java.io.File; + +import org.gcube.common.validator.annotations.IsValid; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.persistence.PersistenceWriter; + +public class PersistenceWriterTest implements PersistenceWriter{ + + @IsValid @NotNull + String location; + + @Override + public File file(String path) { + return null; + } + + @Override + public File writefile(String path) { + return null; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + +} diff --git a/src/test/java/utils/TestUtils.java b/src/test/java/utils/TestUtils.java index 61ebc8e..a148ca3 100644 --- a/src/test/java/utils/TestUtils.java +++ b/src/test/java/utils/TestUtils.java @@ -1,7 +1,5 @@ package utils; -import java.io.File; -import java.io.FileWriter; import java.io.StringWriter; import java.util.ArrayList; import java.util.List; @@ -13,7 +11,6 @@ import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.handlers.application.ApplicationHandler; @@ -41,34 +38,7 @@ public class TestUtils { } - /** - * Serialises a {@link ContainerConfiguration} to XML in a file. - * - * @param config the configuration - * @param the file - * @return the serialisation - * @throws RuntimeException if the configuration cannot be serialised - */ - public static void serialise(ContainerConfiguration config, File file) { - - //serialises configuration - - try { - JAXBContext ctx = JAXBContext.newInstance(ContainerConfiguration.class); - - FileWriter writer = new FileWriter(file); - - ctx.createMarshaller().marshal(config, writer); - - writer.flush(); - writer.close(); - - } catch (Exception e) { - - throw new RuntimeException("invalid service configuration", e); - } - } /** * Serialises a {@link ApplicationConfiguration} to XML. * diff --git a/src/test/resources/test-configuration.ini b/src/test/resources/test-configuration.ini new file mode 100644 index 0000000..d3b2c8d --- /dev/null +++ b/src/test/resources/test-configuration.ini @@ -0,0 +1,41 @@ +[node] +; mandatory +; optional fields: mode (online), publication-frequency-seconds (=60), authorizeChildrenContext (=false) +mode = offline +hostname = localhost +protocol= https +port = 8080 +infrastructure = gcube +authorizeChildrenContext = true +publicationFrequencyInSeconds = 60 + +[properties] +; not mandatory +SmartGearsDistribution = 0.0.1 +SmartGearsDistributionBundle = UnBundled + +[site] +; mandatory +country = it +location = rome +latitude = 41.9000 +longitude = 12.5000 + +[proxy] +; not mandatory +protocol = https +hostname = proxy +port = 80 + +[authorization] +; mandatory +; optional fields: provider (org.gcube.smartgears.security.DefaultAuthorizationProvider) +provider = org.gcube.smartgears.security.DefaultAuthorizationProvider +credentials.class = org.gcube.smartgears.security.SimpleCredentials +credentials.clientID = testClient +credentials.secret = testSecret + +[persistence] +; not mandatory (default is LocalPersistence writing in the ghn home) +class = test.container.PersistenceWriterTest +location = /state From 08b3cd590a3809c0ee13a7078d9fb5dff7643f83 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Mon, 21 Mar 2022 11:17:07 +0100 Subject: [PATCH 10/49] new features for configuration file type changing --- distro/smartgears-config.xml | 2 - pom.xml | 24 +- .../java/org/gcube/smartgears/Bootstrap.java | 2 +- .../application/ApplicationConfiguration.java | 3 + .../BridgedApplicationConfiguration.java | 11 + .../DefaultApplicationConfiguration.java | 12 + .../configuration/container/Site.java | 4 - .../library/SmartGearsConfiguration.java | 6 +- .../application/ApplicationContext.java | 4 +- .../DefaultApplicationContext.java | 9 +- .../context/container/ContainerContext.java | 3 +- .../container/DefaultContainerContext.java | 9 +- .../resource/FrontPageResource.java | 3 +- .../extensions/resource/ProfileResource.java | 3 +- .../handlers/AbstractProfilePublisher.java | 138 ++++++++++ .../smartgears/handlers/ProfilePublisher.java | 19 +- .../application/lifecycle/ProfileBuilder.java | 3 +- .../application/lifecycle/ProfileManager.java | 6 +- .../lifecycle/ProfilePublisherImpl.java | 201 --------------- .../lifecycle/ServicePublisher.java | 62 +++++ .../lifecycle/ContainerPublisher.java | 55 ++++ .../container/lifecycle/ProfileBuilder.java | 8 +- .../container/lifecycle/ProfileManager.java | 6 +- .../lifecycle/ProfilePublisherImpl.java | 241 ------------------ .../managers/ApplicationManager.java | 14 +- .../smartgears/managers/ContainerManager.java | 96 ++----- .../persistence/LocalPersistence.java | 14 +- .../smartgears/provider/DefaultProvider.java | 147 ++++------- .../gcube/smartgears/provider/Provider.java | 20 +- .../security/AuthorizationProvider.java | 4 +- .../DefaultAuthorizationProvider.java | 7 +- src/test/java/app/Request.java | 69 ++--- src/test/java/app/SomeApp.java | 2 +- .../test/SmartgearsConfigurationTest.java | 37 --- .../application/ProfileManagementTest.java | 4 +- .../test/application/RemoteResourceTest.java | 4 +- .../java/test/application/StartupTest.java | 4 +- .../test/container/ConfigurationTest.java | 3 +- .../test/container/ProfileManagementTest.java | 8 +- src/test/java/test/container/StartupTest.java | 2 +- .../PersistenceWriterTest.java | 11 +- src/test/java/utils/TestProvider.java | 20 +- src/test/resources/test-configuration.ini | 11 +- 43 files changed, 505 insertions(+), 806 deletions(-) delete mode 100644 distro/smartgears-config.xml create mode 100644 src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java create mode 100644 src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java create mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java delete mode 100644 src/test/java/test/SmartgearsConfigurationTest.java rename src/test/java/{test/container => utils}/PersistenceWriterTest.java (78%) diff --git a/distro/smartgears-config.xml b/distro/smartgears-config.xml deleted file mode 100644 index ffa7124..0000000 --- a/distro/smartgears-config.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index fcc1b7c..a5ab099 100644 --- a/pom.xml +++ b/pom.xml @@ -28,8 +28,8 @@ distro - 7.0.42 - 1.17.1 + 8.0.42 + 2.25.1 UTF-8 @@ -154,9 +154,8 @@ - com.sun.jersey + org.glassfish.jersey.core jersey-client - ${jersey.version} test @@ -227,6 +226,20 @@ + + org.apache.maven.plugins + maven-surefire-plugin + + + + projectVersion + ${project.version} + + + + + + org.apache.maven.plugins @@ -280,9 +293,6 @@ ${distroDirectory} - - smartgears-config.xml - true diff --git a/src/main/java/org/gcube/smartgears/Bootstrap.java b/src/main/java/org/gcube/smartgears/Bootstrap.java index 088f496..1428436 100644 --- a/src/main/java/org/gcube/smartgears/Bootstrap.java +++ b/src/main/java/org/gcube/smartgears/Bootstrap.java @@ -90,7 +90,7 @@ public class Bootstrap implements ServletContainerInitializer { * using gcube facilities annotation based * ( i.e org.gcube.common.validator.annotations) */ - //context.configuration().validate(); + context.configuration().validate(); } catch (RuntimeException e) { diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index cbc85d6..bcfb21a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -115,6 +115,9 @@ public interface ApplicationConfiguration { */ ApplicationConfiguration persistence(PersistenceWriter manager); + void authorizedContexts(Set authorizedContexts); + + Set authorizedContexts(); /** * Validates this configuration. diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java index 7ab9517..64414a5 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java @@ -134,5 +134,16 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration return application.proxyAddress(proxyaddress); } + @Override + public void authorizedContexts(Set authorizedContexts) { + application.authorizedContexts(authorizedContexts); + + } + + @Override + public Set authorizedContexts() { + return application.authorizedContexts(); + } + } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java index 4c34ee8..0427fff 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java @@ -57,6 +57,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElementRef Set includes= new LinkedHashSet(); + Set authorizedContexts; @NotNull @IsValid private PersistenceWriter persistenceManager; @@ -169,6 +170,16 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration return this; } + @Override + public void authorizedContexts(Set authorizedContexts) { + this.authorizedContexts = authorizedContexts; + } + + + @Override + public Set authorizedContexts() { + return this.authorizedContexts; + } @Override public void validate() { @@ -197,5 +208,6 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration } + } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/container/Site.java b/src/main/java/org/gcube/smartgears/configuration/container/Site.java index 2c22935..da6aec1 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/Site.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/Site.java @@ -16,14 +16,10 @@ public class Site { @NotNull String location; - @NotNull String latitude; - @NotNull String longitude; - - public String getCountry() { return country; } diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java index 1541837..f628c6a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java @@ -3,18 +3,14 @@ package org.gcube.smartgears.configuration.library; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.NotEmpty; -@XmlRootElement(name="smartgears") public class SmartGearsConfiguration { - @XmlAttribute @NotEmpty + @NotEmpty private String version; public SmartGearsConfiguration(){ diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java index b24640a..a7a8f06 100644 --- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java @@ -3,6 +3,7 @@ package org.gcube.smartgears.context.application; import javax.servlet.ServletContext; import org.gcube.common.events.Hub; +import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; @@ -35,7 +36,7 @@ public interface ApplicationContext { ApplicationConfiguration configuration(); - T profile(Class type); + GCoreEndpoint profile(); /** * Returns the lifecycle of the application. @@ -79,4 +80,5 @@ public interface ApplicationContext { */ Properties properties(); + } diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index fbe0328..9536401 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -66,13 +66,8 @@ public class DefaultApplicationContext implements ApplicationContext { } @Override - @SuppressWarnings("all") - public T profile(Class type) { - - if (type==GCoreEndpoint.class) - return (T) properties().lookup(profile_property).value(GCoreEndpoint.class); - - throw new IllegalArgumentException("unsupported profile type: "+type); + public GCoreEndpoint profile() { + return properties().lookup(profile_property).value(GCoreEndpoint.class); } @Override diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index 6afb028..c1f043b 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -1,6 +1,7 @@ package org.gcube.smartgears.context.container; import org.gcube.common.events.Hub; +import org.gcube.common.resources.gcore.HostingNode; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; @@ -25,7 +26,7 @@ public interface ContainerContext { * Returns the resource profile of a given type of the container. * @return the profile */ - T profile(Class type); + HostingNode profile(); /** * Returns the lifecycle of the container diff --git a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java index 7d5fe14..64fbfac 100644 --- a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java @@ -38,13 +38,8 @@ public class DefaultContainerContext implements ContainerContext { this.properties=properties; } - @SuppressWarnings("all") - public T profile(Class type) { - - if (type==HostingNode.class) - return (T) properties().lookup(container_profile_property).value(HostingNode.class); - - throw new IllegalArgumentException("unsupported profile type: "+type); + public HostingNode profile() { + return properties().lookup(container_profile_property).value(HostingNode.class); }; @Override diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index a587d0c..d3e175a 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -23,7 +23,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; @@ -95,7 +94,7 @@ public class FrontPageResource extends ApiResource { String infrastructure = context().container().configuration().infrastructure(); StringBuilder voValue = new StringBuilder(); - Collection scopes = context().profile(GCoreEndpoint.class).scopes().asCollection(); + Collection scopes = context().profile().scopes().asCollection(); Set vos = new HashSet(); //pre-process diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java index 9e76f66..58b6182 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java @@ -9,7 +9,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.common.resources.gcore.Resources; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; @@ -36,7 +35,7 @@ public class ProfileResource extends ApiResource { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Resources.marshal(context().profile(GCoreEndpoint.class),resp.getWriter()); + Resources.marshal(context().profile(),resp.getWriter()); } } diff --git a/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java b/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java new file mode 100644 index 0000000..eaa3752 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java @@ -0,0 +1,138 @@ +package org.gcube.smartgears.handlers; + +import static org.gcube.smartgears.utils.Utils.notEmpty; +import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Set; + +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.resources.gcore.Resource; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.informationsystem.publisher.ScopedPublisher; +import org.gcube.smartgears.provider.ProviderFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public abstract class AbstractProfilePublisher

implements ProfilePublisher { + + private static final Logger log = LoggerFactory.getLogger(AbstractProfilePublisher.class); + + //the underlying IS publisher + private final ScopedPublisher publisher; + + //private AuthorizationProvider authProvider ; + + public AbstractProfilePublisher() { + this.publisher=ProviderFactory.provider().publisher(); + //this.authProvider = ProviderFactory.provider().authorizationProvider(); + } + + protected abstract P getProfile(); + protected abstract boolean isRoot(); + protected abstract void sharePublished(P profile); + protected abstract Set getAllowedContexts(); + + /** + * Removes the application from one or more scopes. + * @param scopes the scopes + */ + public void removeFrom(Collection contexts) { + P profile = getProfile(); + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + + log.debug("using context {}",contextCL.getClass().getSimpleName()); + + String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); + try{//This classloader set is needed for the jaxb context + if (previousToken!=null) + SecurityTokenProvider.instance.reset(); + if (isRoot()) + Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); + profile = publisher.remove(profile, new ArrayList(contexts)); + + } catch (Exception e) { + rethrowUnchecked(e); + } finally{ + SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); + if (isRoot()) + Thread.currentThread().setContextClassLoader(contextCL); + } + log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection()); + sharePublished(profile); + } + + + public void addToAll(){ + this.addTo(getAllowedContexts()); + } + + /** + * Adds for the first time the current resource profile of the application in one or more scopes. + * @param contexts the contexts + */ + public void addTo(Collection contexts) { + notEmpty("contexts",contexts); + + P profile = getProfile(); + + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + + log.debug("using context {}",contextCL.getClass().getSimpleName()); + + String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); + try{//This classloader set is needed for the jaxb context + if (previousToken!=null) + SecurityTokenProvider.instance.reset();; + if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); + ScopeProvider.instance.set(contexts.stream().findFirst().get()); + profile = publisher.create(profile, new ArrayList(contexts)); + + } catch (Exception e) { + rethrowUnchecked(e); + } finally{ + SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); + if (isRoot()) Thread.currentThread().setContextClassLoader(contextCL); + } + + sharePublished(profile); + log.debug("shared profile with scopes {}", profile.scopes().asCollection()); + } + + + + public void update() { + P profile = getProfile(); + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + + log.debug("using context {}",contextCL.getClass().getSimpleName()); + + String previousToken = SecurityTokenProvider.instance.get(); + String previousScope = ScopeProvider.instance.get(); + try{//This classloader set is needed for the jaxb context + if (previousToken!=null) + SecurityTokenProvider.instance.reset(); + + if (isRoot()) + Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); + profile = publisher.update(profile); + + } catch (Exception e) { + rethrowUnchecked(e); + } finally{ + SecurityTokenProvider.instance.set(previousToken); + ScopeProvider.instance.set(previousScope); + if (isRoot()) + Thread.currentThread().setContextClassLoader(contextCL); + } + + sharePublished(profile); + } + + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java b/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java index 6c3e374..c928c50 100644 --- a/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java +++ b/src/main/java/org/gcube/smartgears/handlers/ProfilePublisher.java @@ -3,21 +3,14 @@ package org.gcube.smartgears.handlers; import java.util.Collection; public interface ProfilePublisher { - - /** - * Adds for the first time the current resource profile of the application in one or more scopes. - * @param scopes the scopes - */ - void addTo(Collection tokens); + + void addTo(Collection contexts); void addToAll(); - + void update(); - /** - * Removes the application from one or more scopes. - * @param scopes the scopes - */ - void removeFrom(Collection tokens); + void removeFrom(Collection contexts); -} \ No newline at end of file + +} diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java index 2caf451..4c57d0a 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java @@ -8,7 +8,6 @@ import java.util.List; import javax.servlet.ServletRegistration; import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.common.resources.gcore.HostingNode; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; @@ -38,7 +37,7 @@ public class ProfileBuilder { .serviceClass(configuration.serviceClass()) .version(configuration.version()) .serviceId(configuration.name() + configuration.serviceClass() + configuration.version()) - .ghnId(context.container().profile(HostingNode.class).id()); + .ghnId(context.container().profile().id()); endpoint.profile().newDeploymentData() .activationTime(Calendar.getInstance()) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java index 5859cb8..8aa9daa 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java @@ -94,7 +94,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { share(profile); publisher = context.container().configuration().mode()!=Mode.offline? - new ProfilePublisherImpl(context): + new ServicePublisher(context): new OfflineProfilePublisher(); @@ -109,7 +109,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { @Observes({ activation, stop, failure }) void onChanged(ApplicationLifecycle lc) { - GCoreEndpoint profile = context.profile(GCoreEndpoint.class); + GCoreEndpoint profile = context.profile(); profile.profile().deploymentData().status(lc.state().remoteForm()); @@ -270,7 +270,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { final Runnable updateTask = new Runnable() { public void run() { - GCoreEndpoint profile = context.profile(GCoreEndpoint.class); + GCoreEndpoint profile = context.profile(); //if handling of event generates failures these will be reported //for resilience we do not fail the application diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java deleted file mode 100644 index 269a99e..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfilePublisherImpl.java +++ /dev/null @@ -1,201 +0,0 @@ -package org.gcube.smartgears.handlers.application.lifecycle; - -import static org.gcube.smartgears.handlers.ProfileEvents.published; -import static org.gcube.smartgears.utils.Utils.notEmpty; -import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.ProfilePublisher; -import org.gcube.smartgears.provider.ProviderFactory; -import org.gcube.smartgears.security.AuthorizationProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Publishes the current resource profile of the application. - *

- *Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update()}. - * - * - * @author Fabio Simeoni - * - */ -public class ProfilePublisherImpl implements ProfilePublisher { - - private static final Logger log = LoggerFactory.getLogger(ProfilePublisherImpl.class); - - //the underlying IS publisher - private final ScopedPublisher publisher; - - private final ApplicationContext context; - - private AuthorizationProvider authProxy ; - - /** - * Creates an instance for a given application. - * @param context the context of the application - */ - public ProfilePublisherImpl(ApplicationContext context) { - this.context = context; - this.publisher=ProviderFactory.provider().publisherFor(context); - this.authProxy = context.container().configuration().authorizationProvider(); - } - - /** - * Adds for the first time the current resource profile of the application in one or more scopes. - * @param scopes the scopes - */ - @Override - public void addTo(Collection contexts) { - - notEmpty("tokens",contexts); - - GCoreEndpoint profile = context.profile(GCoreEndpoint.class); - - /* TODO: reintroduce it when scope will be removed - //TODO: remove when move to new IS - Collection retainedContexts = new ArrayList(context.container().configuration().allowedContexts()); - retainedContexts.removeAll(profile.scopes().asCollection()); - profile.scopes().asCollection().addAll(retainedContexts); - - - String previousToken = SecurityTokenProvider.instance.get(); - try { - for (String token: tokens){ - log.info("creating profile with token {}", token); - SecurityTokenProvider.instance.set(token); - profile = publisher.create(profile); - SecurityTokenProvider.instance.reset(); - } - }catch (Exception e) { - rethrowUnchecked(e); - } finally{ - SecurityTokenProvider.instance.set(previousToken); - } - */ - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset();; - if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - ScopeProvider.instance.set(contexts.stream().findFirst().get()); - profile = publisher.create(profile, new ArrayList(contexts)); - - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); - if (context.container().configuration().mode()!=Mode.root) Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - log.debug("shared profile with scopes {}", profile.scopes().asCollection()); - } - - @Override - public void addToAll() { - this.addTo(context.configuration().allowedContexts()); - } - - - @Override - public void update() { - - - GCoreEndpoint profile = context.profile(GCoreEndpoint.class); - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset(); - - if (context.container().configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.update(profile); - - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); - if (context.container().configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - } - - - /** - * Removes the application from one or more scopes. - * @param scopes the scopes - */ - @Override - public void removeFrom(Collection contexts) { - - GCoreEndpoint profile = context.profile(GCoreEndpoint.class); - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset(); - if (context.container().configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.remove(profile, contexts); - - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); - if (context.container().configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(contextCL); - } - log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection()); - sharePublished(profile); - } - - - - private void sharePublished(GCoreEndpoint profile) { - context.events().fire(profile,published); - } - - private List resolveScopesFromTokens(Collection tokens){ - List scopes = new ArrayList(tokens.size()); - for (String token: tokens) - try{ - scopes.add(this.authProxy.get(token).getContext()); - }catch (Exception e) { - log.warn("error retrieving token {} , it should never happen",token); - } - return scopes; - } - -} diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java new file mode 100644 index 0000000..538834b --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java @@ -0,0 +1,62 @@ +package org.gcube.smartgears.handlers.application.lifecycle; + +import java.util.List; +import java.util.Set; + +import org.gcube.common.resources.gcore.GCoreEndpoint; +import org.gcube.common.resources.gcore.HostingNode; +import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.smartgears.handlers.AbstractProfilePublisher; +import org.gcube.smartgears.handlers.ProfileEvents; + +/** + * Publishes the current resource profile of the application. + *

+ *Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update()}. + * + * + * @author Fabio Simeoni + * + */ +public class ServicePublisher extends AbstractProfilePublisher { + + private final ApplicationContext context; + + public ServicePublisher(ApplicationContext context) { + super(); + this.context = context; + } + + + protected void sharePublished(HostingNode profile) { + context.events().fire(profile,ProfileEvents.published); + } + + + @Override + protected GCoreEndpoint getProfile() { + return context.profile(); + } + + + @Override + protected boolean isRoot() { + return context.container().configuration().mode()!=Mode.root; + } + + + @Override + protected void sharePublished(GCoreEndpoint profile) { + context.events().fire(profile,ProfileEvents.published); + } + + + @Override + protected Set getAllowedContexts() { + // TODO Auto-generated method stub + return null; + } +} + + diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java new file mode 100644 index 0000000..bbf7110 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java @@ -0,0 +1,55 @@ +package org.gcube.smartgears.handlers.container.lifecycle; + +import java.util.List; +import java.util.Set; + +import org.gcube.common.resources.gcore.HostingNode; +import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.handlers.AbstractProfilePublisher; +import org.gcube.smartgears.handlers.ProfileEvents; + +/** + * Publishes the resource profile of the container. + *

+ * Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update(List)}. + * + * @author Fabio Simeoni + * + */ +public class ContainerPublisher extends AbstractProfilePublisher { + + + private final ContainerContext context; + + public ContainerPublisher(ContainerContext context) { + super(); + this.context = context; + } + + + protected void sharePublished(HostingNode profile) { + context.events().fire(profile,ProfileEvents.published); + } + + + @Override + protected HostingNode getProfile() { + return context.profile(); + } + + + @Override + protected boolean isRoot() { + return context.configuration().mode()!=Mode.root; + } + + + @Override + protected Set getAllowedContexts() { + // TODO Auto-generated method stub + return null; + } + + +} diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java index 73b6e32..4315a6b 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java @@ -9,8 +9,6 @@ import java.io.Reader; import java.math.BigDecimal; import java.net.InetAddress; import java.net.UnknownHostException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.util.ArrayList; import java.util.Calendar; import java.util.HashMap; @@ -193,7 +191,7 @@ public class ProfileBuilder { long free = 0; try { free = context.configuration().persistence().getFreeSpace()/1024; - } catch (IOException ioe) { + } catch (Exception ioe) { log.warn("unable to detect the free space on the disk", ioe); } return free; @@ -241,8 +239,8 @@ public class ProfileBuilder { ContainerConfiguration cfg = context.configuration(); - node.profile().newSite().country(cfg.site().country()).location(cfg.site().location()) - .latitude(cfg.site().latitude()).longitude(cfg.site().longitude()).domain(domainIn(cfg.hostname())); + node.profile().newSite().country(cfg.site().getCountry()).location(cfg.site().getLocation()) + .latitude(cfg.site().getLatitude()).longitude(cfg.site().getLongitude()).domain(domainIn(cfg.hostname())); } private void addVariablesTo(HostingNode node) { diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java index ad9a450..e420768 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java @@ -87,7 +87,7 @@ public class ProfileManager extends ContainerHandler { share(profile); publisher = context.configuration().mode()!=Mode.offline? - new ProfilePublisherImpl(context): + new ContainerPublisher(context): new OfflineProfilePublisher(); registerObservers(); @@ -102,7 +102,7 @@ public class ProfileManager extends ContainerHandler { @Observes({ activation, part_activation, shutdown, stop, failure }) void onChanged(ContainerLifecycle lc) { - HostingNode profile = context.profile(HostingNode.class); + HostingNode profile = context.profile(); profile.profile().description().status(lc.state().remoteForm()); @@ -245,7 +245,7 @@ public class ProfileManager extends ContainerHandler { final Runnable updateTask = new Runnable() { public void run() { - HostingNode profile = context.profile(HostingNode.class); + HostingNode profile = context.profile(); try { builder.update(profile, false); diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java deleted file mode 100644 index f40a4a5..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfilePublisherImpl.java +++ /dev/null @@ -1,241 +0,0 @@ -package org.gcube.smartgears.handlers.container.lifecycle; - -import static org.gcube.smartgears.utils.Utils.notEmpty; -import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.handlers.ProfileEvents; -import org.gcube.smartgears.handlers.ProfilePublisher; -import org.gcube.smartgears.provider.ProviderFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Publishes the resource profile of the container. - *

- * Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update(List)}. - * - * @author Fabio Simeoni - * - */ -public class ProfilePublisherImpl implements ProfilePublisher { - - private static final Logger log = LoggerFactory.getLogger(ProfilePublisherImpl.class); - - //the underlying IS publisher - private final ScopedPublisher publisher; - //private final AuthorizationProvider authorization; - private final ContainerContext context; - - private AuthorizationProxy authProxy ; - - /** - * Creates an instance for the container. - * @param context the context of the application - */ - public ProfilePublisherImpl(ContainerContext context) { - this.context = context; - this.publisher=ProviderFactory.provider().publisherFor(context); - this.authProxy = ProviderFactory.provider().authorizationProxy(); - } - - /** - * Adds the current resource profile of the application in one or more - * scopes. The scopes are retrieved from tokens - * @param tokens the tokens - */ - public void addTo(Collection tokens) { - - notEmpty("tokens",tokens); - - log.info("publishing container with tokens {}", tokens); - - HostingNode profile = context.profile(HostingNode.class); - - /* TODO: reintroduce it when scope will be removed - //TODO: remove when move to new IS - Collection retainedContexts = new ArrayList(context.configuration().allowedContexts()); - retainedContexts.removeAll(profile.scopes().asCollection()); - profile.scopes().asCollection().addAll(retainedContexts); - - log.trace("profile scopes on create are {} ",profile.scopes().asCollection()); - - String previousToken = SecurityTokenProvider.instance.get(); - - try { - for (String token: tokens){ - log.info("creating profile with token {}", token); - SecurityTokenProvider.instance.set(token); - profile = publisher.create(profile); - SecurityTokenProvider.instance.reset(); - } - - update(); - - } catch (Exception e) { - log.warn("error adding scopes",e); - rethrowUnchecked(e); - - } finally{ - SecurityTokenProvider.instance.set(previousToken); - }*/ - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)tokens.toArray()[0]); - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.create(profile, resolveScopesFromTokens(tokens)); - } catch (Exception e) { - rethrowUnchecked(e); - } finally { - SecurityTokenProvider.instance.set(previousToken); - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - - } - - /** - * Adds the current resource profile of the application in one or more scopes. - */ - public void addToAll() { - addTo(context.configuration().startTokens()); - } - - /** - * Updates the current resource profile of the application in its current scopes. - */ - public void update() { - - HostingNode profile = context.profile(HostingNode.class); - /* TODO: reintroduce it when scope will be removed - Collection tokens = context.configuration().startTokens(); - - log.info("updating container with tokens {}", tokens); - - String previousToken = SecurityTokenProvider.instance.get(); - - try { - for (String token: tokens){ - SecurityTokenProvider.instance.set(token); - profile = publisher.update(profile); - SecurityTokenProvider.instance.reset(); - } - sharePublished(profile); - - } - catch (Exception e) { - log.warn("error updating container",e); - rethrowUnchecked(e); - - } finally{ - SecurityTokenProvider.instance.set(previousToken); - }*/ - - - log.debug("[update] resource scopes are : {} ",profile.scopes().asCollection()); - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)context.configuration().startTokens().toArray()[0]); - - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.update(profile); - } catch (Exception e) { - rethrowUnchecked(e); - } finally { - SecurityTokenProvider.instance.set(previousToken); - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - } - - /** - * Removes the container from one or more scopes. - * @param tokens the tokens - */ - public void removeFrom(Collection tokens) { - - HostingNode profile = context.profile(HostingNode.class); - - log.info("removing container with tokens {}", tokens); - - /* TODO: reintroduce it when scope will be removed - String previousToken = SecurityTokenProvider.instance.get(); - - try { - - for (String token: tokens){ - SecurityTokenProvider.instance.set(token); - profile = publisher.remove(profile); - SecurityTokenProvider.instance.reset(); - } - - update(); - - } - catch (Exception e) { - log.warn("error removing scopes",e); - rethrowUnchecked(e); - - } finally{ - SecurityTokenProvider.instance.set(previousToken); - } */ - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - try{//This classloader set is needed for the jaxb context - if (previousToken==null) - SecurityTokenProvider.instance.set((String)tokens.toArray()[0]); - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(ProfilePublisherImpl.class.getClassLoader()); - profile = publisher.remove(profile, resolveScopesFromTokens(tokens)); - } catch (Exception e) { - rethrowUnchecked(e); - } finally { - SecurityTokenProvider.instance.set(previousToken); - if (context.configuration().mode()!=Mode.root) - Thread.currentThread().setContextClassLoader(contextCL); - } - - log.debug("after remove container profile contains scopes {}",profile.scopes().asCollection()); - sharePublished(profile); - } - - private void sharePublished(HostingNode profile) { - context.events().fire(profile,ProfileEvents.published); - } - - private List resolveScopesFromTokens(Collection tokens){ - List scopes = new ArrayList(tokens.size()); - for (String token: tokens) - try{ - scopes.add(this.authProxy.get(token).getContext()); - }catch (Exception e) { - log.warn("error retrieving token {} , it should never happen",token); - } - return scopes; - } -} diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index 0ed56a8..c1622dd 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -15,7 +15,6 @@ import java.io.ObjectOutputStream; import java.util.Collection; import java.util.List; import java.util.Map.Entry; -import java.util.stream.Collectors; import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; @@ -69,18 +68,11 @@ public class ApplicationManager { for (Entry servlet : application.getServletRegistrations().entrySet()) log.trace("servlet {} : {} {} ", application.getServletContextName(),servlet.getKey(), servlet.getValue().getMappings()); - - - - /* if (context.configuration().secure() && - container.configuration().securePort()==null) - throw new IllegalStateException( - String.format("Application %s cannot be managed because is declared as secure without a secure connector port declared in the container", context.application().getContextPath())); - */ if (context.container().configuration().mode()!=Mode.offline) { - context.configuration().startTokens(generateTokensForApplication(container).stream().collect(Collectors.toSet())); + context.configuration().authorizedContexts(context.container().configuration().allowedContexts()); context.configuration().validate(); + //TODO take information from container to configure application } saveApplicationState(); @@ -93,8 +85,6 @@ public class ApplicationManager { ApplicationHandlers handlers = provider().handlersFor(context); handlers.validate(); - - ApplicationExtensions extensions = provider().extensionsFor(context); extensions.validate(); diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 92ae6d8..96e777e 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -10,29 +10,21 @@ import static org.gcube.smartgears.provider.ProviderFactory.provider; import java.io.File; import java.io.FileOutputStream; import java.io.ObjectOutputStream; -import java.util.HashSet; import java.util.List; import java.util.Set; -import org.gcube.common.authorization.client.exceptions.ObjectNotFound; -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; -import org.gcube.common.authorization.library.AuthorizationEntry; -import org.gcube.common.authorization.library.provider.ClientInfo; -import org.gcube.common.authorization.library.provider.ContainerInfo; import org.gcube.common.events.Observes; import org.gcube.common.events.Observes.Kind; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.container.ContainerHandlers; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.handlers.ProfileEvents; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; import org.gcube.smartgears.handlers.container.ContainerPipeline; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerState; import org.gcube.smartgears.security.AuthorizationProvider; -import org.gcube.smartgears.security.Credentials; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -49,8 +41,6 @@ public class ContainerManager { public static ContainerManager instance = new ContainerManager(); - private AuthorizationProvider authProvider = provider().authorizationProxy(); - private ContainerContext context; private ContainerPipeline pipeline; @@ -113,57 +103,26 @@ public class ContainerManager { private void validateContainer(ContainerContext context) { //List tokensToRemove = new ArrayList(); context.configuration().validate(); - Set foundContexts= new HashSet(); - - Credentials credential = context.configuration().credentials(); + Set foundContexts; + try { - List entries = authProvider.get(context.configuration().startTokens()); - - log.info("requesting auth on {} tokens returned {} entries", context.configuration().startTokens().size(),entries.size()); - - for (AuthorizationEntry entry : entries ) { - log.info("the container will be started in context {}",entry.getContext()); - foundContexts.add(entry.getContext()); - } - + foundContexts = context.configuration().allowedContexts(); } catch (Exception e) { - log.error("error contacting auth service on container",e); + log.error("error authorizing container",e); + throw new RuntimeException("error authorizing container, moving the container to failed",e); } if (foundContexts.isEmpty()){ - log.error("no valid starting token are specified, moving the container to failed"); - throw new RuntimeException("no valid starting token are specified"); + log.error("no valid contexts found, moving the container to failed"); + throw new RuntimeException("no valid contexts found, moving the container to failed"); } + //context.configuration().startTokens().removeAll(tokensToRemove); context.configuration().allowedContexts(foundContexts); } - private String resolveTokenForAdd(Set alreadyAddedContext, String token){ - try { - AuthorizationEntry entry = authProvider.get(token); - ClientInfo info = entry.getClientInfo(); - log.info("resolved authorization entry for container {}",entry); - if (alreadyAddedContext.contains(entry.getContext())){ - log.warn("the token {} cannot be used, another token with the same context {} found ", entry.getContext()); - } else if(!entry.getContext().startsWith("/"+context.configuration().infrastructure())){ - log.warn("the token {} cannot be used, is not in the infrastructure {} of the container ", token,context.configuration().infrastructure()); - }else if (!(info instanceof ContainerInfo)){ - log.warn("the token {} cannot be used, is not for a container token ", token); - } else if (!((ContainerInfo)info).getHost().equals(context.configuration().hostname()) - || context.configuration().port()!=((ContainerInfo)info).getPort()){ - log.warn("the token {} cannot be used, the client id {} resolved with the token is not the same of the one specified in this container ", token, info.getId()); - } else - return entry.getContext(); - }catch(ObjectNotFound onf){ - log.error("token {} not valid", token); - } catch (Exception e) { - log.error("error contacting authorization for token {}",token,e); - } - return null; - } - public void manage(ApplicationContext app) { app.events().subscribe(this); @@ -175,40 +134,15 @@ public class ContainerManager { context.lifecycle().tryMoveTo(ContainerState.partActive); } - @Observes(value=ContextEvents.ADD_TOKEN_TO_CONTAINER,kind=Kind.critical) - void addToken(String token) { - log.trace("adding token {} to container", token); - String newContext; - if ((newContext = resolveTokenForAdd(context.configuration().allowedContexts(), token))!=null) { - context.configuration().startTokens().add(token); - context.configuration().allowedContexts().add(newContext); - saveContainerState(); - //loadKeyForToken(Arrays.asList(token)); - context.events().fire(token, ContextEvents.ADD_TOKEN_TO_APPLICATION); - context.events().fire(token, ProfileEvents.addToContext); - log.trace("token added and event fired"); - } else log.warn("trying to add an invalid token"); + @Observes(value=ContextEvents.ADD_CONTEXT_TO_CONTAINER,kind=Kind.critical) + void addContext(String context) { + log.trace("adding context {} to container", context); + } - @Observes(value=ContextEvents.REMOVE_TOKEN_FROM_CONTAINER,kind=Kind.critical) - void removeToken(String token) { - log.trace("removing token {} from container", token); - AuthorizationEntry entry; - try { - entry = authProvider.get(token); - } catch (Exception e) { - log.error("error resolving token to remove"); - return; - } - - if (context.configuration().startTokens().contains(token)) { - context.configuration().startTokens().remove(token); - context.configuration().allowedContexts().remove(entry.getContext()); - saveContainerState(); - context.events().fire(token, ContextEvents.REMOVE_TOKEN_FROM_APPLICATION); - context.events().fire(token, ProfileEvents.removeFromContext); - log.trace("token removed and event fired"); - } else log.warn("cannot remove token, it is not present in the container"); + @Observes(value=ContextEvents.REMOVE_CONTEXT_FROM_CONTAINER,kind=Kind.critical) + void removeContext(String context) { + log.trace("removing context {} from container", context); } /** diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java index 9e9ca85..e298a53 100644 --- a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java +++ b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java @@ -5,6 +5,8 @@ import static org.gcube.smartgears.utils.Utils.fileAt; import static org.gcube.smartgears.utils.Utils.notNull; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Paths; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; @@ -50,10 +52,7 @@ public class LocalPersistence implements PersistenceWriter { return fileAt(new File(location, path).getAbsolutePath()).toRead(); } - void initialize(){ - } - public void validate() { File locationDir = new File(location); @@ -61,5 +60,14 @@ public class LocalPersistence implements PersistenceWriter { throw new IllegalStateException("invalid node configuration: home "+location+" does not exist or is not a directory or cannot be accessed in read/write mode"); } + + @Override + public long getFreeSpace() { + try { + return Files.getFileStore(Paths.get(location)).getUsableSpace(); + }catch (Exception e) { + return -1; + } + } } diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 0bf1e8e..a113e56 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -1,10 +1,9 @@ package org.gcube.smartgears.provider; -import static org.gcube.common.authorization.client.Constants.authorizationService; +import static org.gcube.smartgears.Constants.application_handlers_file_name; import static org.gcube.smartgears.Constants.configuration_file_path; import static org.gcube.smartgears.Constants.container_configuraton_file_path; import static org.gcube.smartgears.Constants.container_handlers_file_name; -import static org.gcube.smartgears.Constants.application_handlers_file_name; import static org.gcube.smartgears.Constants.container_handlers_file_path; import static org.gcube.smartgears.Constants.container_profile_file_path; import static org.gcube.smartgears.Constants.default_extensions_file_path; @@ -25,11 +24,10 @@ import java.net.URLClassLoader; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; -import java.util.List; import java.util.UUID; import javax.servlet.ServletContext; -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; + import org.gcube.common.events.Hub; import org.gcube.common.events.impl.DefaultHub; import org.gcube.common.scan.ClasspathScanner; @@ -56,7 +54,7 @@ import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.context.container.DefaultContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; -import org.gcube.smartgears.persistence.DefaultPersistence; +import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -74,24 +72,33 @@ public class DefaultProvider implements Provider { private ContainerContext containerContext; //TODO: do the same with applicationContext (with a map) + + private File configFile = null; + + protected DefaultProvider(File configFile) { + this.configFile = configFile; + } + + protected DefaultProvider(){}; - @SuppressWarnings("unchecked") @Override public ContainerContext containerContext() { if(containerContext==null){ ContainerConfiguration configuration = containerConfiguration(); - + + + /* if (configuration.persistence()==null) { String location = Utils.home()+"/state"; File dir = new File(location); if (!dir.exists()) dir.mkdirs(); - configuration.persistence(new DefaultPersistence(location)); + configuration.persistence(new LocalPersistence(location)); log.trace("setting persistence location for container @ {}",dir.getAbsolutePath()); - } + }*/ Hub hub = new DefaultHub(); @@ -100,12 +107,10 @@ public class DefaultProvider implements Provider { File file = configuration.persistence().file(container_profile_file_path); String id = null; - List tokens = null; if (file.exists()){ log.info("loading persisted state for container"); try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){ id = (String)ois.readObject(); - tokens = (List) ois.readObject(); }catch(Exception e){ log.error("error loading persisted state, creating new uuid",e); } @@ -117,9 +122,6 @@ public class DefaultProvider implements Provider { } - if (tokens!=null) - configuration.startTokens(tokens); - containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, new Properties()); } return containerContext; @@ -137,14 +139,14 @@ public class DefaultProvider implements Provider { ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); ContainerHandlers defaultHandlers = binder.bindHandlers(config); - + ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){ log.trace("probably i'm in a webapp classloader"); currentClassLoader = currentClassLoader.getParent(); } - - + + try{ if (currentClassLoader instanceof URLClassLoader){ URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ; @@ -152,13 +154,13 @@ public class DefaultProvider implements Provider { if (urls!=null && urls.length>0){ ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet(Arrays.asList(urls))); Collection resources = scanner.scan(new NameMatcher(container_handlers_file_name)); - + for (URL url: urls) log.trace("URL: "+ url.toString()); - + if (resources==null || resources.isEmpty()) log.info("no custom container handlers found in the classpath"); - + for (ClasspathResource res : resources){ try{ ContainerHandlers customHandlers= binder.bindHandlers(res.stream()); @@ -190,8 +192,6 @@ public class DefaultProvider implements Provider { ApplicationConfiguration embedded = configurationFor(application); ApplicationConfiguration external = context.configuration().app(application.getContextPath()); - - //shouldn't happen: management shouldn't have started at all if (embedded==null && external==null) throw new AssertionError("application @ "+application.getContextPath()+" is not distributed with " @@ -259,15 +259,15 @@ public class DefaultProvider implements Provider { ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); ApplicationHandlers defaultHandlers = binder.bindHandlers(defaultHandlersStream); - + //searching for smartegars related application handlers in the common classloader ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){ log.trace("probably i'm in a webapp classloader"); currentClassLoader = currentClassLoader.getParent(); } - - + + try{ if (currentClassLoader instanceof URLClassLoader){ URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ; @@ -277,7 +277,7 @@ public class DefaultProvider implements Provider { Collection resources = scanner.scan(new NameMatcher(application_handlers_file_name)); if (resources==null || resources.isEmpty()) log.info("no custom smartgears related application handlers found in the classpath"); - + for (ClasspathResource res : resources){ try{ ApplicationHandlers customHandlers= binder.bindHandlers(res.stream()); @@ -292,9 +292,9 @@ public class DefaultProvider implements Provider { }catch(Exception e){ log.warn("cannot load smartgears related handlers for application from the root classloader",e); } - + InputStream appSpecificHandlersStream = context.application().getResourceAsStream(handlers_file_path); - + if (appSpecificHandlersStream !=null ){ defaultHandlers.mergeWith(binder.bindHandlers(appSpecificHandlersStream)); log.trace("{} uses default lifecycle with app spceific handler as it includes {}", context.name(), handlers_file_path); @@ -349,15 +349,9 @@ public class DefaultProvider implements Provider { try { - InputStream config = getClass().getResourceAsStream(library_configuration_file_path); - - if (config == null) - throw new IllegalStateException("invalid distribution: cannot find " + library_configuration_file_path); - - SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder(); - - SmartGearsConfiguration configuration = binder.bind(config); - + SmartGearsConfiguration configuration = new SmartGearsConfiguration(); + configuration.version(System.getProperty("projectVersion")); + configuration.validate(); return configuration; @@ -371,7 +365,6 @@ public class DefaultProvider implements Provider { } // helpers - private ApplicationConfiguration configurationFor(ServletContext application) { try { @@ -394,76 +387,48 @@ public class DefaultProvider implements Provider { private ContainerConfiguration containerConfiguration() { - String home = Utils.home(); + if (configFile==null) { + + String home = Utils.home(); + + if (home == null) + throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env + + " or the system property " + ghn_home_property + " must be defined"); - if (home == null) - throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env - + " or the system property " + ghn_home_property + " must be defined"); + File homeDir = new File(home); - File homeDir = new File(home); + if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite())) + throw new IllegalStateException("invalid node configuration: home "+home+" does not exist or is not a directory or cannot be accessed in read/write mode"); - if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite())) - throw new IllegalStateException("invalid node configuration: home "+home+" does not exist or is not a directory or cannot be accessed in read/write mode"); + configFile = new File(homeDir,container_configuraton_file_path); - File config = new File(homeDir,container_configuraton_file_path); - - if (!(config.exists() && config.canRead())) - throw new IllegalStateException("invalid node configuration: file "+config.getAbsolutePath()+" does not exist or cannot be accessed"); - - - log.trace("reading container configuration @ {} ", config.getAbsolutePath()); - - ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); - - FileInputStream stream = null; - try { - - stream = new FileInputStream(config); - - } - catch(Exception e) { - throw new RuntimeException("unexpected exception reading container configuration file see cause)",e); + + log.trace("reading container configuration @ {} ", configFile.getAbsolutePath()); } - ContainerConfiguration configuration = binder.bind(stream); + if (!(configFile.exists() && configFile.canRead())) + throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" does not exist or cannot be accessed"); - try { - stream.close(); + ContainerConfiguration configuration; + try (InputStream stream = new FileInputStream(configFile)){ + configuration= ContainerConfiguration.load(stream); + }catch (Exception e) { + throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid"); } - catch(Exception e) { - log.warn("could not close stream when reading container configuration @ "+config.getAbsolutePath()+" (see cause)",e); - } - + return configuration; } - /* - @Override - public RegistryPublisher publisherFor(ContainerContext context) { - return context.configuration().mode()==Mode.online? - RegistryPublisherFactory.create(): new OfflinePublisher(); - } @Override - public RegistryPublisher publisherFor(ApplicationContext context) { - return context.configuration().mode()==Mode.online? - RegistryPublisherFactory.create(): new OfflinePublisher(); - }*/ - - @Override - public ScopedPublisher publisherFor(ContainerContext context) { - return context.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher() + public ScopedPublisher publisher() { + return containerContext.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher() : new OfflinePublisher(); } - @Override - public ScopedPublisher publisherFor(ApplicationContext context) { - return context.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher() - : new OfflinePublisher(); - } @Override - public AuthorizationProxy authorizationProxy() { - return authorizationService(); + public AuthorizationProvider authorizationProvider() { + return containerContext.configuration().authorizationProvider(); } } diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index 40f1da3..ba3a873 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -2,7 +2,6 @@ package org.gcube.smartgears.provider; import javax.servlet.ServletContext; -import org.gcube.common.authorization.client.proxy.AuthorizationProxy; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; @@ -43,10 +42,9 @@ public interface Provider { /** * Returns an implementation of the IS publisher for the container - * @param application the context of the container * @return the publisher implementation */ - ScopedPublisher publisherFor(ContainerContext application); + ScopedPublisher publisher(); //application-level dependencies @@ -72,19 +70,11 @@ public interface Provider { * @return the extensions */ ApplicationExtensions extensionsFor(ApplicationContext application); - + /** - * Returns an implementation of the IS publisher for a given application - * @param application the context of the application - * @return the publisher implementation + * Returns the authorization provider for this node + * @return the AuthorizationProvider implementation */ - ScopedPublisher publisherFor(ApplicationContext application); - - /** - * Returns an implementation of the IS publisher for a given application - * @param application the context of the application - * @return the publisher implementation - */ - AuthorizationProvider authorizationProxy(); + AuthorizationProvider authorizationProvider(); } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index 13b5e86..afe8b11 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -1,10 +1,10 @@ package org.gcube.smartgears.security; -import java.util.Collection; +import java.util.Set; public interface AuthorizationProvider { void connect(Credentials credentials) throws Exception; - Collection getAllowedContexts(); + Set getAllowedContexts(); } diff --git a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java index 2645fff..82710d9 100644 --- a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java @@ -1,6 +1,6 @@ package org.gcube.smartgears.security; - +import java.util.Set; public class DefaultAuthorizationProvider implements AuthorizationProvider { @@ -11,4 +11,9 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { this.credentials = (SimpleCredentials)credentials; } + @Override + public Set getAllowedContexts() { + return null; + } + } diff --git a/src/test/java/app/Request.java b/src/test/java/app/Request.java index b58b1bf..106f1ea 100644 --- a/src/test/java/app/Request.java +++ b/src/test/java/app/Request.java @@ -1,41 +1,38 @@ package app; -import static com.sun.jersey.api.client.Client.create; -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static org.gcube.smartgears.Constants.scope_header; -import static org.gcube.smartgears.extensions.HttpExtension.Method.DELETE; -import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; -import static utils.TestUtils.context_root; - import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.Map.Entry; import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.logging.Logger; + +import javax.ws.rs.HttpMethod; +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation.Builder; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.library.utils.Caller; -import org.gcube.smartgears.extensions.HttpExtension.Method; +import org.glassfish.jersey.client.ClientConfig; +import org.glassfish.jersey.client.ClientResponse; +import org.glassfish.jersey.logging.LoggingFeature; import utils.TestUtils; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.client.WebResource.Builder; -import com.sun.jersey.api.client.filter.LoggingFilter; -import com.sun.jersey.core.header.OutBoundHeaders; - - public class Request { private String path=""; private String scope = TestUtils.scope; - private OutBoundHeaders headers = new OutBoundHeaders(); - private Method method = GET; + //private OutBoundHeaders headers = new OutBoundHeaders(); + private String method = HttpMethod.GET; private String body = null; private boolean logged = false; + Map> headers = new HashMap<>(); public static Request request() { return new Request(); @@ -66,11 +63,11 @@ public class Request { } public Request with(String name, String value) { - this.headers.add(name, value); + this.headers.put(name, value); return this; } - public Request using(Method method) { + public Request using(String method) { this.method=method; return this; } @@ -83,7 +80,7 @@ public class Request { return body; } - public Method method() { + public String method() { return method; } @@ -101,7 +98,7 @@ public class Request { class Box { - volatile UniformInterfaceException failure; + volatile Exception failure; volatile ClientResponse response; } @@ -116,35 +113,43 @@ public class Request { try { - Client client = create(); - + ClientConfig config = new ClientConfig(); + + + + + Client client = ClientBuilder.newClient(); + + if (logged) - client.addFilter(new LoggingFilter(System.err)); + client.register(new LoggingFeature(Logger.getLogger(getClass().getName()))); - Builder builder = client.resource(address(path,port)) - .entity(body).header(scope_header, scope); + Builder builder = client.target(address(path,port)).request(); + builder.header("gcube-scope", scope); + + for (Entry> header : headers.entrySet()) for (Object value : header.getValue()) builder.header(header.getKey(), value); - if (method==DELETE) + if (method.equals(HttpMethod.DELETE)) builder.delete(); else { System.err.println("making request @ "+address(path,port)); - ClientResponse response = builder.method(method.name(),ClientResponse.class); + ClientResponse response = builder.method(method,ClientResponse.class); //throws an exception if there response has error status if (response.getStatus()>300) - throw new UniformInterfaceException(response); + throw new Exception(response.getStatus()); box.response=response; } - } catch (UniformInterfaceException t) { + } catch (Exception t) { box.failure=t; } @@ -154,7 +159,7 @@ public class Request { try { - if (!latch.await(2000, MILLISECONDS)) + if (!latch.await(2000, TimeUnit.MILLISECONDS)) throw new RuntimeException("application has not responded in time"); } catch (InterruptedException e) { diff --git a/src/test/java/app/SomeApp.java b/src/test/java/app/SomeApp.java index aa108ad..76d5a82 100644 --- a/src/test/java/app/SomeApp.java +++ b/src/test/java/app/SomeApp.java @@ -65,7 +65,7 @@ public class SomeApp { private ApplicationConfiguration configuration; private ApplicationHandlers handlers = new ApplicationHandlers(); private ApplicationExtensions extensions = new ApplicationExtensions(); - private TestProvider provider = new TestProvider(); + private TestProvider provider = new TestProvider(new File("src/test/resources/test-configuration.ini")); private boolean deployHandlers = true; private boolean deployExtensions = true; private boolean deployConfiguration = true; diff --git a/src/test/java/test/SmartgearsConfigurationTest.java b/src/test/java/test/SmartgearsConfigurationTest.java deleted file mode 100644 index 2d67dc8..0000000 --- a/src/test/java/test/SmartgearsConfigurationTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package test; - -import static junit.framework.Assert.*; - -import java.io.ByteArrayInputStream; - -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; -import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder; -import org.junit.Test; - -public class SmartgearsConfigurationTest { - - @Test - public void configurationBinds() throws Exception { - - String xml = ""; - - SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder(); - - SmartGearsConfiguration bound = binder.bind(new ByteArrayInputStream(xml.getBytes())); - - bound.validate(); - - String version = bound.version(); - assertEquals("1.0.0-SNAPSHOT",version); - - assertEquals(sampleSmartgearsConfiguration(),bound); - - - } - - private SmartGearsConfiguration sampleSmartgearsConfiguration() { - - return new SmartGearsConfiguration().version("1.0.0-SNAPSHOT"); - - } -} diff --git a/src/test/java/test/application/ProfileManagementTest.java b/src/test/java/test/application/ProfileManagementTest.java index bed3475..742c891 100644 --- a/src/test/java/test/application/ProfileManagementTest.java +++ b/src/test/java/test/application/ProfileManagementTest.java @@ -33,7 +33,7 @@ public class ProfileManagementTest { @Test public void createsStoresAndPublishesAValidProfile() throws Exception { - GCoreEndpoint profile = ctx.profile(GCoreEndpoint.class); + GCoreEndpoint profile = ctx.profile(); assertNotNull(profile); @@ -64,7 +64,7 @@ public class ProfileManagementTest { ApplicationContext ctx = runtwice.start(); - GCoreEndpoint profile = ctx.profile(GCoreEndpoint.class); + GCoreEndpoint profile = ctx.profile(); assertNotNull(profile); diff --git a/src/test/java/test/application/RemoteResourceTest.java b/src/test/java/test/application/RemoteResourceTest.java index 03188a4..b8314b8 100644 --- a/src/test/java/test/application/RemoteResourceTest.java +++ b/src/test/java/test/application/RemoteResourceTest.java @@ -81,8 +81,8 @@ public class RemoteResourceTest { GCoreEndpoint profile = Resources.unmarshal(GCoreEndpoint.class, new StringReader(outcome)); - assertEquals(context.profile(GCoreEndpoint.class).id(), profile.id()); - assertEquals(context.profile(GCoreEndpoint.class).profile().deploymentData().status(), profile.profile().deploymentData().status()); + assertEquals(context.profile().id(), profile.id()); + assertEquals(context.profile().profile().deploymentData().status(), profile.profile().deploymentData().status()); } diff --git a/src/test/java/test/application/StartupTest.java b/src/test/java/test/application/StartupTest.java index aecc38f..a3f7cdb 100644 --- a/src/test/java/test/application/StartupTest.java +++ b/src/test/java/test/application/StartupTest.java @@ -27,7 +27,7 @@ import org.gcube.smartgears.handlers.application.ApplicationEvent; import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent.Start; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; -import org.gcube.smartgears.persistence.DefaultPersistence; +import org.gcube.smartgears.persistence.LocalPersistence; import org.junit.After; import org.junit.Test; import org.mockito.Matchers; @@ -162,7 +162,7 @@ public class StartupTest { public void canUseMergedConfiguration() { ApplicationConfiguration config = new DefaultApplicationConfiguration(); - config.persistence(new DefaultPersistence(new File(".").getAbsolutePath())); + config.persistence(new LocalPersistence(new File(".").getAbsolutePath())); ApplicationContext context = app.start(); diff --git a/src/test/java/test/container/ConfigurationTest.java b/src/test/java/test/container/ConfigurationTest.java index a20f772..24936fc 100644 --- a/src/test/java/test/container/ConfigurationTest.java +++ b/src/test/java/test/container/ConfigurationTest.java @@ -35,7 +35,6 @@ public class ConfigurationTest { StringWriter sw = new StringWriter(); ini.store(sw); - - System.out.println(sw.toString()); + } } diff --git a/src/test/java/test/container/ProfileManagementTest.java b/src/test/java/test/container/ProfileManagementTest.java index 1b45685..ffcdc22 100644 --- a/src/test/java/test/container/ProfileManagementTest.java +++ b/src/test/java/test/container/ProfileManagementTest.java @@ -24,7 +24,7 @@ public class ProfileManagementTest { ContainerContext ctx = startAppAndGetContainerContext(); - HostingNode node = ctx.profile(HostingNode.class); + HostingNode node = ctx.profile(); assertNotNull(node); @@ -49,9 +49,9 @@ public class ProfileManagementTest { ContainerContext ctx = runtwice.start().container(); - assertNotNull(ctx.profile(HostingNode.class)); + assertNotNull(ctx.profile()); - HostingNode node = ctx.profile(HostingNode.class); + HostingNode node = ctx.profile(); Resources.validate(node); } @@ -62,7 +62,7 @@ public class ProfileManagementTest { SomeApp app = new SomeApp(); - app.containerConfiguration().publicationFrequency(1); + //app.containerConfiguration().publicationFrequency(1); ContainerContext ctx = app.start().container(); diff --git a/src/test/java/test/container/StartupTest.java b/src/test/java/test/container/StartupTest.java index cbb5a0a..db0d4d9 100644 --- a/src/test/java/test/container/StartupTest.java +++ b/src/test/java/test/container/StartupTest.java @@ -43,7 +43,7 @@ public class StartupTest { @Test(expected=RuntimeException.class) public void failsIfConfigurationIsInvalid() { - app.containerConfiguration().hostname(null); + //app.containerConfiguration().hostname(null); app.start(); diff --git a/src/test/java/test/container/PersistenceWriterTest.java b/src/test/java/utils/PersistenceWriterTest.java similarity index 78% rename from src/test/java/test/container/PersistenceWriterTest.java rename to src/test/java/utils/PersistenceWriterTest.java index f593fa5..a73e280 100644 --- a/src/test/java/test/container/PersistenceWriterTest.java +++ b/src/test/java/utils/PersistenceWriterTest.java @@ -1,4 +1,4 @@ -package test.container; +package utils; import java.io.File; @@ -13,12 +13,12 @@ public class PersistenceWriterTest implements PersistenceWriter{ @Override public File file(String path) { - return null; + return new File(location+"/"+path); } @Override public File writefile(String path) { - return null; + return new File(location+"/"+path); } public String getLocation() { @@ -28,5 +28,10 @@ public class PersistenceWriterTest implements PersistenceWriter{ public void setLocation(String location) { this.location = location; } + + @Override + public long getFreeSpace() { + return 0; + } } diff --git a/src/test/java/utils/TestProvider.java b/src/test/java/utils/TestProvider.java index 1d7a295..be3042e 100644 --- a/src/test/java/utils/TestProvider.java +++ b/src/test/java/utils/TestProvider.java @@ -1,17 +1,24 @@ package utils; +import java.io.File; + import javax.servlet.ServletContext; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; +import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.provider.DefaultProvider; public class TestProvider extends DefaultProvider { + public TestProvider(File configFile) { + super(configFile); + } + public ApplicationContext context; public ApplicationConfiguration configuration; public ApplicationHandlers handlers; @@ -34,9 +41,18 @@ public class TestProvider extends DefaultProvider { this.extensions=extensions; } + + @Override - public ScopedPublisher publisherFor(ApplicationContext context) { - return publisher==null?super.publisherFor(context):publisher; + public SmartGearsConfiguration smartgearsConfiguration() { + SmartGearsConfiguration conf = new SmartGearsConfiguration(); + conf.version("0.0.1-TEST"); + return conf ; + } + + @Override + public ScopedPublisher publisher() { + return publisher==null?super.publisher():publisher; } @Override diff --git a/src/test/resources/test-configuration.ini b/src/test/resources/test-configuration.ini index d3b2c8d..28e53ff 100644 --- a/src/test/resources/test-configuration.ini +++ b/src/test/resources/test-configuration.ini @@ -1,6 +1,6 @@ [node] ; mandatory -; optional fields: mode (online), publication-frequency-seconds (=60), authorizeChildrenContext (=false) +; optional fields: mode (=online), publication-frequency-seconds (=60), authorizeChildrenContext (=false) mode = offline hostname = localhost protocol= https @@ -16,10 +16,9 @@ SmartGearsDistributionBundle = UnBundled [site] ; mandatory +; optional fields: latitude, logitude country = it location = rome -latitude = 41.9000 -longitude = 12.5000 [proxy] ; not mandatory @@ -29,7 +28,7 @@ port = 80 [authorization] ; mandatory -; optional fields: provider (org.gcube.smartgears.security.DefaultAuthorizationProvider) +; optional fields: provider (=org.gcube.smartgears.security.DefaultAuthorizationProvider) provider = org.gcube.smartgears.security.DefaultAuthorizationProvider credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.clientID = testClient @@ -37,5 +36,5 @@ credentials.secret = testSecret [persistence] ; not mandatory (default is LocalPersistence writing in the ghn home) -class = test.container.PersistenceWriterTest -location = /state +class = utils.PersistenceWriterTest +location = /tmp From 454533abcd6cca2bf71cb35f0dd98ce03009fe2c Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Tue, 29 Mar 2022 15:05:28 +0200 Subject: [PATCH 11/49] update --- CHANGELOG.md | 4 ++ pom.xml | 1 + .../smartgears/extensions/HttpController.java | 2 - .../smartgears/extensions/HttpExtension.java | 22 +++++- .../request/RequestContextRetriever.java | 2 +- .../application/request/RequestValidator.java | 72 +++++-------------- src/test/java/app/Request.java | 17 +++-- src/test/java/app/SomeApp.java | 5 +- .../test/application/CallValidationTest.java | 11 +-- .../java/test/application/ControllerTest.java | 39 ++++++---- .../java/test/application/ExtensionsTest.java | 9 ++- .../container/ContainerLifecycleTest.java | 10 ++- src/test/java/utils/TestUtils.java | 2 +- 13 files changed, 99 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b35f0ec..f50afed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm - Added SecretManagerProvider thread local from authorization-utils [#22871] - Added Linux distribution version [#22933] +## [v3.1.3] - 2022-03-21 + +- fixed bug on policies + ## [v3.1.2] - 2022-01-19 diff --git a/pom.xml b/pom.xml index a5ab099..9e05530 100644 --- a/pom.xml +++ b/pom.xml @@ -12,6 +12,7 @@ org.gcube.core common-smartgears 4.0.0-SNAPSHOT + SmartGears diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpController.java b/src/main/java/org/gcube/smartgears/extensions/HttpController.java index 8a2d7a7..4c78aa0 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpController.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpController.java @@ -176,8 +176,6 @@ public class HttpController extends HttpExtension { case OPTIONS: resource.doOptions(request, response); break; - case TRACE: - resource.doTrace(request, response); } } diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java index c97a9e7..d8edea6 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java @@ -11,7 +11,7 @@ import javax.xml.bind.annotation.XmlAttribute; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.smartgears.configuration.application.Exclude; import org.gcube.smartgears.context.application.ApplicationContext; - +import javax.ws.rs.HttpMethod; /** * An {@link ApplicationExtension} that implements the {@link HttpServlet} interface * @@ -27,7 +27,25 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx * */ public static enum Method { - GET, PUT, POST, HEAD, DELETE, OPTIONS, TRACE + GET(HttpMethod.GET), + PUT(HttpMethod.PUT), + POST(HttpMethod.POST), + HEAD(HttpMethod.HEAD), + DELETE(HttpMethod.DELETE), + OPTIONS(HttpMethod.OPTIONS); + + + private String value; + + + private Method(String value) { + this.value = value; + } + + + public String getValue() { + return this.value; + } } @XmlAttribute @NotEmpty diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java index 3ef9060..787baaf 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java @@ -99,4 +99,4 @@ public class RequestContextRetriever extends RequestHandler { SecretManagerProvider.instance.reset(); } -} +} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index b894db1..dff908f 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -1,21 +1,12 @@ package org.gcube.smartgears.handlers.application.request; -import static org.gcube.common.authorization.client.Constants.authorizationService; import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error; import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error; import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; -import java.util.List; - import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.authorization.library.PolicyUtils; -import org.gcube.common.authorization.library.policies.Policy; -import org.gcube.common.authorization.library.policies.User2ServicePolicy; -import org.gcube.common.authorization.library.policies.UserEntity; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.authorization.library.provider.ServiceIdentifier; +import org.gcube.common.authorization.utils.manager.SecretManager; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; @@ -26,7 +17,6 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.application.RequestEvent; import org.gcube.smartgears.handlers.application.RequestHandler; -import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -83,30 +73,30 @@ public class RequestValidator extends RequestHandler { private void validateScopeCall() { - String scope = ScopeProvider.instance.get(); + String context = SecretManagerProvider.instance.get().getContext(); - if (scope == null) { + if (context == null) { log.warn("rejecting unscoped call to {}",appContext.name()); invalid_request_error.fire("call is unscoped"); } - ScopeBean bean = new ScopeBean(scope); + ScopeBean bean = new ScopeBean(context); ContainerConfiguration conf = appContext.container().configuration(); - if (!conf.allowedContexts().contains(scope) && - !(conf.authorizeChildrenContext() && bean.is(Type.VRE) && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) { - log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),scope,appContext.container().configuration().allowedContexts()); - invalid_request_error.fire(appContext.name()+" cannot be called in scope "+scope); + if (!conf.allowedContexts().contains(context) && + !(conf.authorizeChildrenContext() && bean.is(Type.VRE) + && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) { + log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),context,appContext.container().configuration().allowedContexts()); + invalid_request_error.fire(appContext.name()+" cannot be called in scope "+context); } } private void rejectUnauthorizedCalls(RequestEvent call){ - - String token = SecurityTokenProvider.instance.get(); - String context = SecretManagerProvider.instance.get().getContext(); - - if (token == null && context==null){ - log.warn("rejecting call to {}, authorization required",appContext.name(),token); + + SecretManager secretManager = SecretManagerProvider.instance.get(); + + if (secretManager.getCurrentSecretHolder().getSecrets().size()>0){ + log.warn("rejecting call to {}, authorization required",appContext.name()); RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); } } @@ -117,40 +107,10 @@ public class RequestValidator extends RequestHandler { } private void validatePolicy(String scope, RequestEvent call){ - log.info("accessing policy validator in scope {} ", scope); - - ServiceIdentifier serviceIdentifier = Utils.getServiceInfo(call.context()).getServiceIdentifier(); - - String callerId = SecretManagerProvider.instance.get().getUser().getUsername(); - - List policies = null; - try { - policies = authorizationService().getPolicies(scope); - }catch (Exception e) { - invalid_request_error.fire("error contating authorization for polices"); - } - - for (Policy policy: policies) { - log.debug("policy: {}", policy.getPolicyAsString() ); - - if (PolicyUtils.isPolicyValidForClient(policy.getServiceAccess(), serviceIdentifier )) { - boolean toReject = false; - UserEntity entity = (((User2ServicePolicy) policy).getEntity()); - if (entity.getIdentifier()!=null) - toReject = entity.getIdentifier().equals(callerId); - else if (entity.getExcludes().isEmpty()) - toReject = true; - else toReject = !entity.getExcludes().contains(callerId); - if (toReject) { - log.error("rejecting call to {} : {} is not allowed to contact the service ",appContext.name(), callerId); - RequestError.request_not_authorized_error.fire("rejecting call to "+appContext.name()+" for polices: "+callerId+" is not allowed to contact the service: "+serviceIdentifier.getServiceName() ); - } - } - - } - + //TODO: must be re-think } + } diff --git a/src/test/java/app/Request.java b/src/test/java/app/Request.java index 106f1ea..99eae31 100644 --- a/src/test/java/app/Request.java +++ b/src/test/java/app/Request.java @@ -1,6 +1,7 @@ package app; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -10,6 +11,7 @@ import java.util.concurrent.TimeUnit; import java.util.logging.Logger; import javax.ws.rs.HttpMethod; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Invocation.Builder; @@ -17,6 +19,7 @@ import javax.ws.rs.client.Invocation.Builder; import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.UserInfo; import org.gcube.common.authorization.library.utils.Caller; +import org.gcube.smartgears.extensions.HttpExtension.Method; import org.glassfish.jersey.client.ClientConfig; import org.glassfish.jersey.client.ClientResponse; import org.glassfish.jersey.logging.LoggingFeature; @@ -63,12 +66,12 @@ public class Request { } public Request with(String name, String value) { - this.headers.put(name, value); + this.headers.put(name, Collections.singletonList(value)); return this; } - public Request using(String method) { - this.method=method; + public Request using(Method method) { + this.method=method.getValue(); return this; } @@ -98,7 +101,7 @@ public class Request { class Box { - volatile Exception failure; + volatile WebApplicationException failure; volatile ClientResponse response; } @@ -143,13 +146,13 @@ public class Request { //throws an exception if there response has error status if (response.getStatus()>300) - throw new Exception(response.getStatus()); + throw new WebApplicationException(response.getStatus()); box.response=response; } - } catch (Exception t) { + } catch (WebApplicationException t) { box.failure=t; } @@ -178,7 +181,7 @@ public class Request { path = (path.isEmpty() || path.startsWith("/"))?path:"/"+path; - return "http://localhost:" + port+ "/" + context_root+path; + return "http://localhost:" + port+ "/" + TestUtils.context_root+path; } } diff --git a/src/test/java/app/SomeApp.java b/src/test/java/app/SomeApp.java index 76d5a82..9e1483a 100644 --- a/src/test/java/app/SomeApp.java +++ b/src/test/java/app/SomeApp.java @@ -27,14 +27,13 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.managers.ContainerManager; import org.gcube.smartgears.provider.ProviderFactory; +import org.glassfish.jersey.client.ClientResponse; import org.jboss.shrinkwrap.api.ShrinkWrap; import org.jboss.shrinkwrap.api.asset.StringAsset; import org.jboss.shrinkwrap.api.exporter.ZipExporter; import org.jboss.shrinkwrap.api.spec.WebArchive; import org.jboss.shrinkwrap.impl.base.path.BasicPath; -import com.sun.jersey.api.client.ClientResponse; - import utils.TestProvider; import utils.TestUtils; @@ -308,7 +307,7 @@ public class SomeApp { */ public String send(Request call) { - return call.make(port()).getEntity(String.class); + return (String) call.make(port()).getEntity(); } /** diff --git a/src/test/java/test/application/CallValidationTest.java b/src/test/java/test/application/CallValidationTest.java index a980908..e2e8d5b 100644 --- a/src/test/java/test/application/CallValidationTest.java +++ b/src/test/java/test/application/CallValidationTest.java @@ -14,6 +14,8 @@ import static utils.TestUtils.scope; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.ws.rs.WebApplicationException; + import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.application.Exclude; @@ -24,7 +26,6 @@ import org.junit.Test; import app.SomeApp; -import com.sun.jersey.api.client.UniformInterfaceException; public class CallValidationTest { @@ -52,7 +53,7 @@ public class CallValidationTest { try { app.send(request()); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { assertEquals(application_unavailable_error.code(), e.getResponse().getStatus()); } @@ -62,7 +63,7 @@ public class CallValidationTest { try { app.send(request()); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { assertEquals(application_failed_error.code(), e.getResponse().getStatus()); } @@ -82,7 +83,7 @@ public class CallValidationTest { app.send(request().inScope(null));; //call in no scope fail(); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { assertEquals(request_not_authorized_error.code(), e.getResponse().getStatus()); } @@ -101,7 +102,7 @@ public class CallValidationTest { app.send(request().inScope("/bad/scope")); //call in no scope fail(); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { assertEquals(invalid_request_error.code(), e.getResponse().getStatus()); } diff --git a/src/test/java/test/application/ControllerTest.java b/src/test/java/test/application/ControllerTest.java index cbdbb97..13fcf34 100644 --- a/src/test/java/test/application/ControllerTest.java +++ b/src/test/java/test/application/ControllerTest.java @@ -1,31 +1,42 @@ package test.application; -import static app.Request.*; -import static org.gcube.smartgears.Constants.*; -import static org.gcube.smartgears.extensions.ApiResource.*; -import static org.gcube.smartgears.extensions.HttpExtension.Method.*; -import static org.gcube.smartgears.handlers.application.request.RequestError.*; -import static org.junit.Assert.*; +import static app.Request.request; +import static org.gcube.smartgears.Constants.accept; +import static org.gcube.smartgears.Constants.allow; +import static org.gcube.smartgears.Constants.content_type; +import static org.gcube.smartgears.extensions.ApiResource.handles; +import static org.gcube.smartgears.extensions.ApiResource.method; +import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; +import static org.gcube.smartgears.extensions.HttpExtension.Method.POST; +import static org.gcube.smartgears.extensions.HttpExtension.Method.PUT; +import static org.gcube.smartgears.handlers.application.request.RequestError.incoming_contenttype_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.method_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.outgoing_contenttype_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.resource_notfound_error; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.ws.rs.WebApplicationException; import org.gcube.smartgears.Constants; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; import org.gcube.smartgears.extensions.HttpController; import org.gcube.smartgears.extensions.HttpExtension; +import org.glassfish.jersey.client.ClientResponse; import org.junit.Test; import app.Request; import app.SomeApp; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.UniformInterfaceException; - public class ControllerTest { String name = "name"; @@ -74,7 +85,7 @@ public class ControllerTest { try { app.send(request); fail(); - } catch (UniformInterfaceException e) { + } catch (WebApplicationException e) { assertEquals(resource_notfound_error.code(), e.getResponse().getStatus()); } } @@ -91,7 +102,7 @@ public class ControllerTest { try { app.send(request); fail(); - } catch (UniformInterfaceException e) { + } catch (WebApplicationException e) { assertEquals(method_unsupported_error.code(), e.getResponse().getStatus()); assertNotNull(e.getResponse().getHeaders().toString(),e.getResponse().getHeaders().get(allow)); } @@ -109,7 +120,7 @@ public class ControllerTest { try { app.send(request); fail(); - } catch (UniformInterfaceException e) { + } catch (WebApplicationException e) { assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); } @@ -127,7 +138,7 @@ public class ControllerTest { try { app.send(request); fail(); - } catch (UniformInterfaceException e) { + } catch (WebApplicationException e) { assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); } } @@ -189,7 +200,7 @@ public class ControllerTest { try { app.send(request); fail(); - } catch (UniformInterfaceException e) { + } catch (WebApplicationException e) { assertEquals(incoming_contenttype_unsupported_error.code(), e.getResponse().getStatus()); } } diff --git a/src/test/java/test/application/ExtensionsTest.java b/src/test/java/test/application/ExtensionsTest.java index 030fb8a..59b86cd 100644 --- a/src/test/java/test/application/ExtensionsTest.java +++ b/src/test/java/test/application/ExtensionsTest.java @@ -12,6 +12,7 @@ import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; +import javax.ws.rs.WebApplicationException; import javax.xml.bind.annotation.XmlRootElement; import org.gcube.smartgears.Constants; @@ -24,8 +25,6 @@ import org.junit.Test; import app.SomeApp; -import com.sun.jersey.api.client.UniformInterfaceException; - public class ExtensionsTest { String name = "name"; @@ -144,7 +143,7 @@ public class ExtensionsTest { app.send(request().at(Constants.root_mapping+extension_path)); fail(); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { assertEquals(error.code(),e.getResponse().getStatus()); } @@ -177,9 +176,9 @@ public class ExtensionsTest { app.send(request().at(Constants.root_mapping+extension_path).inScope(null)); fail(); } - catch(UniformInterfaceException e) { + catch(WebApplicationException e) { - assertEquals(e.getResponse().getEntity(String.class),invalid_request_error.code(),e.getResponse().getStatus()); + assertEquals((String)e.getResponse().getEntity(),invalid_request_error.code(),e.getResponse().getStatus()); } } } diff --git a/src/test/java/test/container/ContainerLifecycleTest.java b/src/test/java/test/container/ContainerLifecycleTest.java index 91a2cf0..87f387b 100644 --- a/src/test/java/test/container/ContainerLifecycleTest.java +++ b/src/test/java/test/container/ContainerLifecycleTest.java @@ -8,6 +8,7 @@ import org.gcube.smartgears.lifecycle.application.ApplicationState; import org.gcube.smartgears.lifecycle.container.ContainerState; import org.gcube.smartgears.managers.ContainerManager; import org.junit.After; +import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -15,7 +16,14 @@ import app.SomeApp; public class ContainerLifecycleTest { - SomeApp app = new SomeApp(); + + SomeApp app; + + + @Before + public void init() { + app = new SomeApp(); + } @After public void teardown() { diff --git a/src/test/java/utils/TestUtils.java b/src/test/java/utils/TestUtils.java index a148ca3..a043481 100644 --- a/src/test/java/utils/TestUtils.java +++ b/src/test/java/utils/TestUtils.java @@ -18,7 +18,7 @@ import org.gcube.smartgears.handlers.application.ApplicationHandler; public class TestUtils { - public static String location = "target/ghn-home"; + public static String location = "/tmp/ghn-home"; public static String context_root = "test-app"; public static String context_root_path = "/" + context_root; public static String servlet_name = "test"; From 9947bfbc7df818f508b5610109fc87333e9418f7 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Thu, 31 Mar 2022 11:58:49 +0200 Subject: [PATCH 12/49] update for 4.0.0 --- .../META-INF/smartgears-config.xml | 2 ++ pom.xml | 5 +++ .../java/org/gcube/smartgears/Constants.java | 2 +- .../library/SmartGearsConfiguration.java | 6 +++- .../smartgears/provider/DefaultProvider.java | 13 ++++--- .../DefaultAuthorizationProvider.java | 36 +++++++++++++++++-- 6 files changed, 56 insertions(+), 8 deletions(-) create mode 100644 gcube/extra-resources/META-INF/smartgears-config.xml diff --git a/gcube/extra-resources/META-INF/smartgears-config.xml b/gcube/extra-resources/META-INF/smartgears-config.xml new file mode 100644 index 0000000..5b56d71 --- /dev/null +++ b/gcube/extra-resources/META-INF/smartgears-config.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9e05530..d73d0bb 100644 --- a/pom.xml +++ b/pom.xml @@ -57,6 +57,11 @@ + + org.gcube.common + keycloak-client + [1.0.0,2.0.0-SNAPSHOT) + org.gcube.common diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index e0ec805..dc23857 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -28,7 +28,7 @@ public class Constants { /** * The container configuration file path, relative to the container configuration directory. */ - public static final String container_configuraton_file_path = "smartgears-node.ini"; + public static final String container_configuraton_file_path = "container.ini"; /** diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java index f628c6a..1541837 100644 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java @@ -3,14 +3,18 @@ package org.gcube.smartgears.configuration.library; import java.util.ArrayList; import java.util.List; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.NotEmpty; +@XmlRootElement(name="smartgears") public class SmartGearsConfiguration { - @NotEmpty + @XmlAttribute @NotEmpty private String version; public SmartGearsConfiguration(){ diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index a113e56..334336b 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -349,13 +349,18 @@ public class DefaultProvider implements Provider { try { - SmartGearsConfiguration configuration = new SmartGearsConfiguration(); - configuration.version(System.getProperty("projectVersion")); - + InputStream config = getClass().getResourceAsStream(library_configuration_file_path); + + if (config == null) + throw new IllegalStateException("invalid distribution: cannot find " + library_configuration_file_path); + + SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder(); + + SmartGearsConfiguration configuration = binder.bind(config); + configuration.validate(); return configuration; - } catch (RuntimeException e) { throw new RuntimeException("cannot read library configuration (see cause) ", e); diff --git a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java index 82710d9..dd6a2e9 100644 --- a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java @@ -1,10 +1,26 @@ package org.gcube.smartgears.security; +import java.util.Collections; +import java.util.HashSet; +import java.util.Map; import java.util.Set; +import org.gcube.common.keycloak.KeycloakClient; +import org.gcube.common.keycloak.KeycloakClientFactory; +import org.gcube.common.keycloak.model.AccessToken.Access; +import org.gcube.common.keycloak.model.ModelUtils; +import org.gcube.common.keycloak.model.TokenResponse; +import org.gcube.common.scope.impl.ScopeBean; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class DefaultAuthorizationProvider implements AuthorizationProvider { - SimpleCredentials credentials; + private static Logger LOG = LoggerFactory.getLogger(DefaultAuthorizationProvider.class); + + private SimpleCredentials credentials; + + private KeycloakClient client = KeycloakClientFactory.newInstance(); @Override public void connect(Credentials credentials) { @@ -13,7 +29,23 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { @Override public Set getAllowedContexts() { - return null; + Set contexts = new HashSet(); + try { + TokenResponse response = client.queryOIDCToken(credentials.getClientID(), credentials.getSecret()); + Map resourceAccess = ModelUtils.getAccessTokenFrom(response).getResourceAccess(); + for (String context : resourceAccess.keySet()) { + try { + ScopeBean scope = new ScopeBean(context.replaceAll("%2F", "/")); + contexts.add(scope.toString()); + }catch (IllegalArgumentException e) { + LOG.warn("invalid context found in token: {}", context); + } + } + } catch (Exception e) { + LOG.error("error getting OIDToken from keycloak",e); + return Collections.emptySet(); + } + return contexts; } } From f6e49975d058d87ad55088757d1ce0d5ec60db75 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 4 May 2022 19:11:33 +0200 Subject: [PATCH 13/49] added import of authorization-util --- pom.xml | 11 ++++++----- .../application/request/RequestAccounting.java | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pom.xml b/pom.xml index d73d0bb..6c73acf 100644 --- a/pom.xml +++ b/pom.xml @@ -63,6 +63,12 @@ [1.0.0,2.0.0-SNAPSHOT) + + org.gcube.common + authorization-utils + [2.0.0-SNAPSHOT,3.0.0-SNAPSHOT) + + org.gcube.common authorization-client @@ -73,11 +79,6 @@ common-authorization - - org.gcube.common - authorization-utils - - org.gcube.data.publishing document-store-lib diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 97dff80..3f7bab3 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -1,13 +1,12 @@ package org.gcube.smartgears.handlers.application.request; -import static org.gcube.smartgears.Constants.called_method_header; - import javax.xml.bind.annotation.XmlRootElement; import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; import org.gcube.accounting.persistence.AccountingPersistenceFactory; +import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider; @@ -38,7 +37,7 @@ public class RequestAccounting extends RequestHandler { public void handleRequest(RequestEvent e) { ApplicationContext context = e.context(); - String calledMethod = e.request().getHeader(called_method_header); + String calledMethod = e.request().getHeader(Constants.called_method_header); if (calledMethod==null){ calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); if (calledMethod.isEmpty()) @@ -84,6 +83,7 @@ public class RequestAccounting extends RequestHandler { InnerMethodName.instance.reset(); if (resetScope) ScopeProvider.instance.reset(); + } void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){ From a285c20b388d3a62f6b5fa8427b225afa55e65bf Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 23 May 2022 17:15:46 +0200 Subject: [PATCH 14/49] removed context retriver handler and merged with Request validator --- CHANGELOG.md | 2 +- pom.xml | 39 +++---- .../java/org/gcube/smartgears/Bootstrap.java | 19 ++++ .../extensions/resource/MetricsResource.java | 44 ++++++++ .../extensions/resource/RemoteResource.java | 2 +- .../request/RequestAccounting.java | 98 ++++++++++------- .../request/RequestContextRetriever.java | 102 ------------------ .../application/request/RequestValidator.java | 57 +++++++--- .../smartgears/managers/ContainerManager.java | 1 - .../smartgears/provider/DefaultProvider.java | 2 +- .../resources/META-INF/default-handlers.xml | 1 - src/main/resources/META-INF/profile.xml | 29 +++++ 12 files changed, 213 insertions(+), 183 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java create mode 100644 src/main/resources/META-INF/profile.xml diff --git a/CHANGELOG.md b/CHANGELOG.md index f50afed..54716a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## [v4.0.0-SNAPSHOT] - +- porting to keycloak ## [v3.2.0-SNAPSHOT] diff --git a/pom.xml b/pom.xml index 6c73acf..b17f221 100644 --- a/pom.xml +++ b/pom.xml @@ -20,7 +20,7 @@ org.gcube.distribution gcube-bom - 2.1.0-SNAPSHOT + 3.0.0-SNAPSHOT pom import @@ -56,29 +56,11 @@ gcube-jackson-core - org.gcube.common - keycloak-client - [1.0.0,2.0.0-SNAPSHOT) + common-security - - - org.gcube.common - authorization-utils - [2.0.0-SNAPSHOT,3.0.0-SNAPSHOT) - - - - org.gcube.common - authorization-client - - - - org.gcube.common - common-authorization - - + org.gcube.data.publishing document-store-lib @@ -130,10 +112,23 @@ javax.servlet javax.servlet-api - 3.0.1 + 4.0.1 provided + + + io.micrometer + micrometer-core + 1.9.0 + + + + io.micrometer + micrometer-registry-prometheus + 1.9.0 + + diff --git a/src/main/java/org/gcube/smartgears/Bootstrap.java b/src/main/java/org/gcube/smartgears/Bootstrap.java index 1428436..f5df24a 100644 --- a/src/main/java/org/gcube/smartgears/Bootstrap.java +++ b/src/main/java/org/gcube/smartgears/Bootstrap.java @@ -14,6 +14,14 @@ import org.gcube.smartgears.provider.ProviderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; +import io.micrometer.core.instrument.binder.system.ProcessorMetrics; +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; + /** * Bootstraps management of all deployed applications which require it. * @@ -86,6 +94,17 @@ public class Bootstrap implements ServletContainerInitializer { /* Get the ContainerContext. Look at DefaultProvider */ context = ProviderFactory.provider().containerContext(); + PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + new ClassLoaderMetrics().bindTo(registry); + new JvmMemoryMetrics().bindTo(registry); + //new JvmGcMetrics().bindTo(registry); + new ProcessorMetrics().bindTo(registry); + new JvmThreadMetrics().bindTo(registry); + + Metrics.addRegistry(registry); + + /* Validate the configuration retrieved by ContainerContext * using gcube facilities annotation based * ( i.e org.gcube.common.validator.annotations) diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java new file mode 100644 index 0000000..d2aa7f3 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java @@ -0,0 +1,44 @@ +package org.gcube.smartgears.extensions.resource; + +import static org.gcube.smartgears.Constants.plain_text; +import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.gcube.smartgears.extensions.ApiResource; +import org.gcube.smartgears.extensions.ApiSignature; + +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; +import io.micrometer.core.instrument.binder.system.ProcessorMetrics; +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; + +public class MetricsResource extends ApiResource { + + private static final long serialVersionUID = 1L; + + public static final String mapping = "/metrics"; + + private static final ApiSignature signature = handles(mapping).with(method(GET).produces(plain_text)); + + + MetricsResource() { + super(signature); + } + + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrometheusMeterRegistry registry = (PrometheusMeterRegistry) Metrics.globalRegistry.getRegistries().stream().findFirst().get(); + registry.scrape(resp.getWriter()); + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java index 1acbf96..475c1d8 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java @@ -27,7 +27,7 @@ public class RemoteResource extends HttpController { public RemoteResource() { super(remote_management, default_mapping); addResources(new FrontPageResource(), new ConfigurationResource(), new ProfileResource(), - new LifecycleResource()); + new LifecycleResource(), new MetricsResource()); } @Override diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 3f7bab3..74f6f03 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -1,14 +1,14 @@ package org.gcube.smartgears.handlers.application.request; +import java.util.concurrent.TimeUnit; + import javax.xml.bind.annotation.XmlRootElement; import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.authorization.library.provider.AuthorizationProvider; import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.authorization.utils.manager.SecretManagerProvider; import org.gcube.common.scope.api.ScopeProvider; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; @@ -20,23 +20,28 @@ import org.gcube.smartgears.utils.InnerMethodName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.micrometer.core.instrument.Metrics; +import io.micrometer.core.instrument.Timer; +import io.micrometer.core.instrument.Timer.Sample; + @XmlRootElement(name = Constants.request_accounting) public class RequestAccounting extends RequestHandler { private static Logger log = LoggerFactory.getLogger(RequestAccounting.class); private static ThreadLocal startCallThreadLocal = new ThreadLocal(); - - + + + @Override public String getName() { return Constants.request_accounting; } - + @Override public void handleRequest(RequestEvent e) { ApplicationContext context = e.context(); - + String calledMethod = e.request().getHeader(Constants.called_method_header); if (calledMethod==null){ calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); @@ -45,45 +50,58 @@ public class RequestAccounting extends RequestHandler { calledMethod= e.request().getMethod()+" "+calledMethod; } InnerMethodName.instance.set(calledMethod); - String caller = SecretManagerProvider.instance.get().getUser().getUsername(); + String caller = "Unknown"; startCallThreadLocal.set(System.currentTimeMillis()); + log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), caller, e.request().getRemoteHost(), ScopeProvider.instance.get()); - + } @Override public void handleResponse(ResponseEvent e) { ApplicationContext context = e.context(); - - boolean resetScope = false; - if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){ - String infrastructure = e.context().container().configuration().infrastructure(); - ScopeProvider.instance.set("/"+infrastructure); - resetScope = true; + + try { + boolean resetScope = false; + if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){ + String infrastructure = e.context().container().configuration().infrastructure(); + ScopeProvider.instance.set("/"+infrastructure); + resetScope = true; + } + + String caller = "Unknown"; + String callerQualifier = "UNKNOWN"; + //retieves caller Ip when there is a proxy + String callerIp = e.request().getHeader("x-forwarded-for"); + if(callerIp==null) + callerIp=e.request().getRemoteHost(); + + boolean success = e.response().getStatus()<400; + + if (context.container().configuration().mode()!=Mode.offline) + generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context); + + long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); + + Metrics.globalRegistry.timer("http.requests", "response",Integer.toString(e.response().getStatus()) + , "context", ScopeProvider.instance.get(), "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, + "caller-username", caller, "service-class", context.configuration().serviceClass(), "service-name", context.configuration().name(), + "method", InnerMethodName.instance.get()).record(durationInMillis, TimeUnit.MILLISECONDS); + + log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", + context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), + caller, callerIp, ScopeProvider.instance.get(), success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); + startCallThreadLocal.remove(); + InnerMethodName.instance.reset(); + if (resetScope) + ScopeProvider.instance.reset(); + }catch (Exception e1) { + log.error("error on accounting",e); + throw e1; } - - String caller = SecretManagerProvider.instance.get().getUser().getUsername(); - String callerQualifier = "UNKNOWN"; - //retieves caller Ip when there is a proxy - String callerIp = e.request().getHeader("x-forwarded-for"); - if(callerIp==null) - callerIp=e.request().getRemoteHost(); - - boolean success = e.response().getStatus()<400; - - if (context.container().configuration().mode()!=Mode.offline) - generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context); - - log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", - context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, callerIp, ScopeProvider.instance.get(), success?"SUCCEDED":"FAILED", e.response().getStatus(), System.currentTimeMillis()-startCallThreadLocal.get()); - startCallThreadLocal.remove(); - InnerMethodName.instance.reset(); - if (resetScope) - ScopeProvider.instance.reset(); - + } void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){ @@ -91,20 +109,20 @@ public class RequestAccounting extends RequestHandler { AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); try{ - + serviceUsageRecord.setConsumerId(caller); serviceUsageRecord.setCallerQualifier(callerQualifier); serviceUsageRecord.setScope(ScopeProvider.instance.get()); serviceUsageRecord.setServiceClass(context.configuration().serviceClass()); serviceUsageRecord.setServiceName(context.configuration().name()); - + serviceUsageRecord.setHost(context.container().configuration().hostname()+":"+context.container().configuration().port()); serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get()); serviceUsageRecord.setCallerHost(remoteHost); serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); serviceUsageRecord.setDuration(System.currentTimeMillis()-startCallThreadLocal.get()); persistence.account(serviceUsageRecord); - + }catch(Exception ex){ log.warn("invalid record passed to accounting ",ex); } @@ -115,6 +133,6 @@ public class RequestAccounting extends RequestHandler { return getName(); } - - + + } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java deleted file mode 100644 index 787baaf..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestContextRetriever.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.gcube.smartgears.handlers.application.request; - -import static org.gcube.smartgears.Constants.scope_header; -import static org.gcube.smartgears.Constants.token_header; -import static org.gcube.smartgears.handlers.application.request.RequestError.internal_server_error; - -import java.util.Base64; - -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.authorization.utils.manager.SecretManager; -import org.gcube.common.authorization.utils.manager.SecretManagerProvider; -import org.gcube.common.authorization.utils.secret.GCubeSecret; -import org.gcube.common.authorization.utils.secret.JWTSecret; -import org.gcube.common.scope.api.ScopeProvider; -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.handlers.application.RequestEvent; -import org.gcube.smartgears.handlers.application.RequestHandler; -import org.gcube.smartgears.handlers.application.ResponseEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -@XmlRootElement(name = Constants.request_context_retriever) -public class RequestContextRetriever extends RequestHandler { - - private static Logger log = LoggerFactory.getLogger(RequestContextRetriever.class); - - private static final String BEARER_AUTH_PREFIX ="Bearer"; - private static final String BASIC_AUTH_PREFIX ="Basic"; - - - @Override - public String getName() { - return Constants.request_context_retriever; - } - - @Override - public void handleRequest(RequestEvent call) { - String token = call.request().getParameter(token_header)==null? call.request().getHeader(token_header):call.request().getParameter(token_header); - String scope = call.request().getParameter(scope_header)==null? call.request().getHeader(scope_header):call.request().getParameter(scope_header); - - String authHeader = call.request().getHeader(Constants.authorization_header); - - log.trace("authorization header is {}",authHeader); - log.trace("token header is {}", token); - log.trace("scope header is {}", scope); - - String retrievedUser = null; - String accessToken = null; - if (authHeader!=null && !authHeader.isEmpty()) { - if (authHeader.startsWith(BEARER_AUTH_PREFIX)) - accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); - else if (token==null && authHeader.startsWith(BASIC_AUTH_PREFIX)) { - String basicAuthToken = authHeader.substring(BASIC_AUTH_PREFIX.length()).trim(); - String decodedAuth = new String(Base64.getDecoder().decode(basicAuthToken.getBytes())); - String[] splitAuth = decodedAuth.split(":"); - token = splitAuth[1]; - retrievedUser = splitAuth[0]; - } - } - - SecretManager secretManager = new SecretManager(); - SecretManagerProvider.instance.set(secretManager); - - if (accessToken!=null) { - JWTSecret jwtSecret = new JWTSecret(accessToken); - secretManager.addSecret(jwtSecret); - } - - if (token!=null) { - GCubeSecret gCubeSecret = new GCubeSecret(token); - secretManager.addSecret(gCubeSecret); - try { - if (retrievedUser != null && !gCubeSecret.getClientInfo().getId().equals(retrievedUser)) { - internal_server_error.fire("user and token owner are not the same"); - } - }catch (Exception e) { - internal_server_error.fire(e.getMessage()); - } - } - - if(accessToken==null && token==null) { - if(scope!=null) { - ScopeProvider.instance.set(scope); - } - }else { - try { - secretManager.set(); - } catch (Exception e) { - internal_server_error.fire(e.getMessage()); - } - } - - } - - @Override - public void handleResponse(ResponseEvent e) { - log.debug("resetting all the Thread local for this call."); - SecretManagerProvider.instance.reset(); - } - -} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index dff908f..c8a39b3 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -1,34 +1,37 @@ package org.gcube.smartgears.handlers.application.request; +import static org.gcube.smartgears.Constants.token_header; import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error; import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error; import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; -import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlRootElement; -import org.gcube.common.authorization.utils.manager.SecretManager; -import org.gcube.common.authorization.utils.manager.SecretManagerProvider; +import javax.xml.crypto.dsig.keyinfo.RetrievalMethod; + import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; +import org.gcube.common.security.providers.SecretManagerProvider; +import org.gcube.common.security.secrets.GCubeSecret; +import org.gcube.common.security.secrets.JWTSecret; +import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.application.RequestEvent; import org.gcube.smartgears.handlers.application.RequestHandler; +import org.gcube.smartgears.handlers.application.ResponseEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @XmlRootElement(name = Constants.request_validation) public class RequestValidator extends RequestHandler { - @XmlAttribute(required=false, name="oauth") - @Deprecated - boolean oauthCompatibility = false; - private static Logger log = LoggerFactory.getLogger(RequestValidator.class); + private static final String BEARER_AUTH_PREFIX ="Bearer"; + private ApplicationContext appContext; @Override @@ -42,7 +45,9 @@ public class RequestValidator extends RequestHandler { log.trace("executing request validator ON REQUEST"); appContext = call.context(); - + + SecretManagerProvider.instance.set(getSecret(call)); + validateAgainstLifecycle(call); rejectUnauthorizedCalls(call); @@ -54,6 +59,13 @@ public class RequestValidator extends RequestHandler { } + @Override + public void handleResponse(ResponseEvent e) { + log.debug("resetting all the Thread local for this call."); + SecretManagerProvider.instance.reset(); + } + + private void validateAgainstLifecycle(RequestEvent call) { switch(appContext.lifecycle().state()) { @@ -68,7 +80,6 @@ public class RequestValidator extends RequestHandler { //nothing to do, but avoids warnings } - } private void validateScopeCall() { @@ -92,10 +103,10 @@ public class RequestValidator extends RequestHandler { } private void rejectUnauthorizedCalls(RequestEvent call){ - - SecretManager secretManager = SecretManagerProvider.instance.get(); - - if (secretManager.getCurrentSecretHolder().getSecrets().size()>0){ + + Secret secret = SecretManagerProvider.instance.get(); + + if (secret!= null){ log.warn("rejecting call to {}, authorization required",appContext.name()); RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); } @@ -109,8 +120,26 @@ public class RequestValidator extends RequestHandler { private void validatePolicy(String scope, RequestEvent call){ //TODO: must be re-think } - + private Secret getSecret(RequestEvent call){ + String token = call.request().getParameter(token_header)==null? call.request().getHeader(token_header):call.request().getParameter(token_header); + String authHeader = call.request().getHeader(Constants.authorization_header); + + log.trace("authorization header is {}",authHeader); + log.trace("token header is {}", token); + + String accessToken = null; + if (authHeader!=null && !authHeader.isEmpty()) + if (authHeader.startsWith(BEARER_AUTH_PREFIX)) + accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); + + Secret secret = null; + if (accessToken!=null) + secret = new JWTSecret(accessToken); + else if (token!=null) + secret = new GCubeSecret(token); + return secret; + } } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 96e777e..4323232 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -24,7 +24,6 @@ import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; import org.gcube.smartgears.handlers.container.ContainerPipeline; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerState; -import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 334336b..e51d90e 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -132,7 +132,7 @@ public class DefaultProvider implements Provider { try { - InputStream config = getClass().getResourceAsStream(container_handlers_file_path); + //TODO retrieve handler classes if (config == null) throw new IllegalStateException("invalid distribution: cannot find " + container_handlers_file_path); diff --git a/src/main/resources/META-INF/default-handlers.xml b/src/main/resources/META-INF/default-handlers.xml index 39ecdba..d6a1181 100644 --- a/src/main/resources/META-INF/default-handlers.xml +++ b/src/main/resources/META-INF/default-handlers.xml @@ -4,7 +4,6 @@ - diff --git a/src/main/resources/META-INF/profile.xml b/src/main/resources/META-INF/profile.xml new file mode 100644 index 0000000..3bc929b --- /dev/null +++ b/src/main/resources/META-INF/profile.xml @@ -0,0 +1,29 @@ + + + + + Service + + ${description} + ${serviceClass} + common-smartgears + 1.0.0 + + + ${description} + common-smartgears + 4.0.0-SNAPSHOT + + org.gcube.core + common-smartgears + 4.0.0-SNAPSHOT + + Library + + common-smartgears-4.0.0-SNAPSHOT.jar + + + + + + From f54efc1e4e81e2e3c1a2c337c1a33a860ec25a3f Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 25 May 2022 18:56:42 +0200 Subject: [PATCH 15/49] handler configuration removed test removed --- .../java/org/gcube/smartgears/Constants.java | 19 - .../ApplicationConfigurationBinder.java | 76 ++- .../application/ApplicationHandlers.java | 102 +--- .../container/BaseConfiguration.java | 2 - .../container/ContainerConfiguration.java | 153 ++---- .../ContainerConfigurationBinder.java | 196 +++++--- .../container/ContainerHandlers.java | 50 -- .../lifecycle/AccountingManager.java | 3 - ...ager.java => ProfileContainerManager.java} | 7 +- .../managers/ApplicationManager.java | 1 - .../smartgears/managers/ContainerManager.java | 19 +- .../smartgears/provider/DefaultProvider.java | 124 +---- .../gcube/smartgears/provider/Provider.java | 6 +- .../security/AuthorizationProvider.java | 2 - .../AuthorizationProviderFactory.java | 7 + .../security/SimpleCredentials.java | 11 + .../DefaultAuthorizationProvider.java | 17 +- .../DefaultAuthorizationProviderFactory.java | 17 + .../resources/META-INF/container-handlers.xml | 5 - .../resources/META-INF/default-handlers.xml | 10 - ...rs.handlers.application.ApplicationHandler | 4 - ...tgears.handlers.container.ContainerHandler | 2 - src/test/java/app/Request.java | 187 -------- src/test/java/app/SomeApp.java | 437 ------------------ src/test/java/app/TestServlet.java | 30 -- src/test/java/app/web.xml | 15 - src/test/java/test/BinderTest.java | 20 + .../test/application/AppLifecycleTest.java | 36 -- .../test/application/CallValidationTest.java | 214 --------- .../test/application/ConfigurationTest.java | 112 ----- .../java/test/application/ControllerTest.java | 288 ------------ .../java/test/application/ExtensionsTest.java | 184 -------- .../application/ProfileManagementTest.java | 74 --- .../test/application/RemoteResourceTest.java | 129 ------ .../java/test/application/StartupTest.java | 231 --------- .../test/container/ConfigurationTest.java | 40 -- .../container/ContainerLifecycleTest.java | 79 ---- .../test/container/ProfileManagementTest.java | 98 ---- src/test/java/test/container/StartupTest.java | 65 --- src/test/resources/container.ini | 41 ++ src/test/resources/test-configuration.ini | 5 +- 41 files changed, 355 insertions(+), 2763 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java rename src/main/java/org/gcube/smartgears/handlers/container/lifecycle/{ProfileManager.java => ProfileContainerManager.java} (97%) create mode 100644 src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java rename src/main/java/org/gcube/smartgears/security/{ => defaults}/DefaultAuthorizationProvider.java (76%) create mode 100644 src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java delete mode 100644 src/main/resources/META-INF/container-handlers.xml delete mode 100644 src/main/resources/META-INF/default-handlers.xml delete mode 100644 src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler delete mode 100644 src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler delete mode 100644 src/test/java/app/Request.java delete mode 100644 src/test/java/app/SomeApp.java delete mode 100644 src/test/java/app/TestServlet.java delete mode 100644 src/test/java/app/web.xml create mode 100644 src/test/java/test/BinderTest.java delete mode 100644 src/test/java/test/application/AppLifecycleTest.java delete mode 100644 src/test/java/test/application/CallValidationTest.java delete mode 100644 src/test/java/test/application/ConfigurationTest.java delete mode 100644 src/test/java/test/application/ControllerTest.java delete mode 100644 src/test/java/test/application/ExtensionsTest.java delete mode 100644 src/test/java/test/application/ProfileManagementTest.java delete mode 100644 src/test/java/test/application/RemoteResourceTest.java delete mode 100644 src/test/java/test/application/StartupTest.java delete mode 100644 src/test/java/test/container/ConfigurationTest.java delete mode 100644 src/test/java/test/container/ContainerLifecycleTest.java delete mode 100644 src/test/java/test/container/ProfileManagementTest.java delete mode 100644 src/test/java/test/container/StartupTest.java create mode 100644 src/test/resources/container.ini diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index dc23857..1fb9e88 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -38,12 +38,6 @@ public class Constants { public static final String container_profile_file_path_copy = "ghn.xml.copy"; - /** - * The container lifecycle configuration resource path. - */ - public static final String container_handlers_file_path = "/META-INF/container-handlers.xml"; - - public static final String container_handlers_file_name = "gcube-container-handlers.xml"; /** * The library configuration resource path. @@ -62,24 +56,11 @@ public class Constants { public static final long default_container_publication_frequency_in_seconds = 60; - - /** * The application configuration resource path. */ public static final String configuration_file_path = "/WEB-INF/gcube-app.xml"; - /** - * The application lifecycle configuration resource path. - */ - public static final String handlers_file_path = "/WEB-INF/gcube-handlers.xml"; - - /** - * The default application lifecycle configuration resource path. - */ - public static final String default_handlers_file_path = "/META-INF/default-handlers.xml"; - - public static final String application_handlers_file_name = "gcube-application-handlers.xml"; /** * The wildcard exclude directive. diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java index 9a81583..3f0380d 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -1,10 +1,13 @@ package org.gcube.smartgears.configuration.application; -import static org.gcube.smartgears.utils.Utils.*; +import static org.gcube.smartgears.utils.Utils.closeSafely; +import static org.gcube.smartgears.utils.Utils.unchecked; import java.io.InputStream; import java.lang.reflect.Modifier; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.ServiceLoader; import java.util.Set; @@ -12,7 +15,11 @@ import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.handlers.application.ApplicationHandler; +import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; +import org.gcube.smartgears.handlers.application.RequestHandler; +import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; +import org.gcube.smartgears.handlers.application.request.RequestAccounting; +import org.gcube.smartgears.handlers.application.request.RequestValidator; /** * Binds {@link ApplicationConfiguration}s to and from XML serialisations. @@ -54,25 +61,27 @@ public class ApplicationConfigurationBinder { * @return the handlers * @throws RuntimeException if the serialisation is invalid */ - public ApplicationHandlers bindHandlers(InputStream stream) { + public ApplicationHandlers bindHandlers(ClassLoader classLoader) { - //collects handler classes - Set> classes = scanForHandlers(); - - try { - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - return (ApplicationHandlers) ctx.createUnmarshaller().unmarshal(stream); - - } catch (JAXBException e) { - - throw unchecked(e); - - } - finally { - closeSafely(stream); - } + List requestHandlers = new LinkedList(); + + //ADDING BASE Handler (order is important) + requestHandlers.add(new RequestValidator()); + requestHandlers.add(new RequestAccounting()); + + //TODO scan RequestHAndler form classloader + + + List lifecycleHandlers = new LinkedList(); + + //ADDING BASE Handler (order is important) + lifecycleHandlers.add(new ProfileManager()); + + + //TODO scan ApplicationLifecycleHandler form classloader + + return new ApplicationHandlers(lifecycleHandlers, requestHandlers); + } /** @@ -103,28 +112,7 @@ public class ApplicationConfigurationBinder { } } - - - private Set> scanForHandlers() throws RuntimeException { - - @SuppressWarnings("all") - ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationHandler.class); - - Set> scanned = new HashSet>(); - - for (ApplicationHandler handler : handlerLoader) { - Class handlerClass = handler.getClass(); - if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT) - continue; - else - scanned.add(handlerClass); - } - - //add top-level configuration - scanned.add(ApplicationHandlers.class); - - return scanned; - } + private Set> scanForExtensions() throws RuntimeException { @@ -146,4 +134,8 @@ public class ApplicationConfigurationBinder { return scanned; } + + public void scanForApplicationHandlers(ClassLoader currentClassLoader) { + // TODO Auto-generated method stub + } } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java index a0c553c..eade558 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationHandlers.java @@ -1,21 +1,11 @@ package org.gcube.smartgears.configuration.application; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.LinkedList; import java.util.List; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlRootElement; -import org.gcube.common.validator.ValidationError; -import org.gcube.common.validator.Validator; -import org.gcube.common.validator.ValidatorFactory; -import org.gcube.common.validator.annotations.IsValid; import org.gcube.smartgears.handlers.application.ApplicationHandler; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; -import org.w3c.dom.Element; /** * The {@link ApplicationHandler}s that manage the application. @@ -23,24 +13,24 @@ import org.w3c.dom.Element; * @author Fabio Simeoni * */ -@XmlRootElement(name="handlers") public class ApplicationHandlers { - @XmlElement(name="lifecycle") @IsValid - private LifecycleHandlers lifecycleHandlers = new LifecycleHandlers(); + private List lifecycleHandlers = new LinkedList(); - @XmlElement(name="request") @IsValid - private RequestHandlers requestHandlers = new RequestHandlers(); + private List requestHandlers = new LinkedList(); - public ApplicationHandlers() {} + public ApplicationHandlers(List lifecycleHandlers, List requestHandlers) { + this.lifecycleHandlers = lifecycleHandlers; + this.requestHandlers = requestHandlers; + } /** * Returns the {@link ApplicationLifecycleHandler}s for the service. * @return the lifecycle handlers */ public List lifecycleHandlers() { - return lifecycleHandlers.values; + return lifecycleHandlers; } /** @@ -48,8 +38,8 @@ public class ApplicationHandlers { * @param handlers the lifecycle handlers * @return this configuration */ - public ApplicationHandlers set(ApplicationLifecycleHandler ... handlers) { - this.lifecycleHandlers = new LifecycleHandlers(Arrays.asList(handlers)); + public ApplicationHandlers setLifecycleHandlers(List handlers) { + this.lifecycleHandlers = handlers; return this; } @@ -58,7 +48,7 @@ public class ApplicationHandlers { * @return the lifetime handlers */ public List requestHandlers() { - return requestHandlers.values; + return requestHandlers; } /** @@ -66,75 +56,11 @@ public class ApplicationHandlers { * @param handlers the request handlers * @return this configuration */ - public ApplicationHandlers set(RequestHandler ... handlers) { - this.requestHandlers = new RequestHandlers(Arrays.asList(handlers)); + public ApplicationHandlers setRequetHandlers(List handlers) { + this.requestHandlers = handlers; return this; } - - public void validate() { - - List msgs = new ArrayList(); - - Validator validator = ValidatorFactory.validator(); - - for (ValidationError error : validator.validate(this)) - msgs.add(error.toString()); - - if (!msgs.isEmpty()) - throw new IllegalStateException("invalid configuration: "+msgs); - - } - - //////////////// HELPER BINDING CLASSES - - //used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension - - private static class LifecycleHandlers { - - @SuppressWarnings("all") - LifecycleHandlers() { //needed for deserialisation - } - - LifecycleHandlers(List handlers) { - this.values=handlers; - } - - @XmlAnyElement(lax=true) - List values = new ArrayList(); - - - //since we use @AnyElement, after deserialisation, we check there are no DOM elements - @SuppressWarnings("unused") - void afterUnmarshal(Unmarshaller u, Object parent) { - for (Object o : values) - if (o instanceof Element) - throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName()); - } - - } - - //used internally to introduce level of nesting in JAXB whilst preserving arbitrary extension - private static class RequestHandlers { - - @SuppressWarnings("all") - RequestHandlers() { //needed for deserialisation - } - - RequestHandlers(List handlers) { - this.values=handlers; - } - - @XmlAnyElement(lax=true) - List values = new ArrayList(); - - //since we use @AnyElement, after deserialisation, we check there are no DOM elements - @SuppressWarnings("unused") - void afterUnmarshal(Unmarshaller u, Object parent) { - for (Object o : values) - if (o instanceof Element) - throw new RuntimeException("invalid handler detected in configuration: "+Element.class.cast(o).getLocalName()); - } - } + public void mergeWith(ApplicationHandlers other){ List lifecycles = other.lifecycleHandlers(); diff --git a/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java index 9fdcb45..31af311 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/BaseConfiguration.java @@ -85,8 +85,6 @@ public class BaseConfiguration { this.infrastructure = infrastructure; } - - @Override public String toString() { diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index ba6dc3b..a897a71 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -1,16 +1,12 @@ package org.gcube.smartgears.configuration.container; -import java.io.File; -import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Map.Entry; import java.util.Set; -import java.util.stream.Collectors; import javax.xml.bind.annotation.XmlTransient; @@ -23,14 +19,8 @@ import org.gcube.common.validator.annotations.NotNull; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; -import org.gcube.smartgears.security.Credentials; -import org.gcube.smartgears.security.DefaultAuthorizationProvider; -import org.gcube.smartgears.utils.Utils; -import org.ini4j.Ini; -import org.ini4j.Profile.Section; /** * The configuration of the container. @@ -69,6 +59,35 @@ public class ContainerConfiguration { @NotNull @IsValid private AuthorizationProvider authorizationProvider; + + protected void setBaseConfiguration(BaseConfiguration baseConfiguration) { + this.baseConfiguration = baseConfiguration; + } + + protected void setProperties(Map properties) { + this.properties = properties; + } + + protected void setSite(Site site) { + this.site = site; + } + + protected void setProxy(ProxyAddress proxy) { + this.proxy = proxy; + } + + protected void setAccountingFallbackLocation(String accountingFallbackLocation) { + this.accountingFallbackLocation = accountingFallbackLocation; + } + + protected void setPersistenceManager(PersistenceWriter persistenceManager) { + this.persistenceManager = persistenceManager; + } + + protected void setAuthorizationProvider(AuthorizationProvider authorizationProvider) { + this.authorizationProvider = authorizationProvider; + } + /** * Returns the management mode for the container. * @return the management mode @@ -243,116 +262,14 @@ public class ContainerConfiguration { } - public static ContainerConfiguration load(InputStream stream) { - try { - Ini configurator = new Ini(stream); - ContainerConfiguration conf = new ContainerConfiguration(); - - Section nodeSection = configurator.get("node"); - if (nodeSection != null ) { - BaseConfiguration nodeConf = new BaseConfiguration(); - nodeSection.to(nodeConf); - conf.baseConfiguration = nodeConf; - } - - Section propertiesSection = configurator.get("properties"); - if (propertiesSection!=null) - conf.properties = propertiesSection.entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); - - Section siteSection = configurator.get("site"); - if (siteSection != null) { - Site siteConf = new Site(); - siteSection.to(siteConf); - conf.site = siteConf; - } - - initAuthorizationPart(configurator, conf); - - initPersistencePart(configurator, conf); - - initProxyPart(configurator, conf); - - - //TODO: find a solution for this shit - String location = Utils.home()+"/state"; - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); - conf.accountingFallbackLocation = location; - // END Shit - - return conf; - }catch (Exception e) { - throw new RuntimeException(e); - } + @Override + public String toString() { + return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties + + ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation + + ", persistenceManager=" + persistenceManager.getClass().getSimpleName() + + ", authorizationProvider=" + authorizationProvider.getClass().getSimpleName() + "]"; } - private static void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{ - Section proxySection = configurator.get("proxy"); - if (proxySection != null) { - ProxyAddress proxyConf = new ProxyAddress(); - proxySection.to(proxyConf); - conf.proxy = proxyConf; - } - } - private static void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{ - Section persistenceSection = configurator.get("persistence"); - if (persistenceSection != null) { - String type = persistenceSection.get("class"); - if (type ==null) - throw new Exception("ini file error: type not found in \"persistence\" section"); - PersistenceWriter persistenceWriter; - try { - Object persistenceImpl = Class.forName(type).newInstance(); - persistenceWriter = PersistenceWriter.class.cast(persistenceImpl); - }catch (Exception e) { - throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e); - } - persistenceSection.to(persistenceWriter); - conf.persistenceManager = persistenceWriter; - } else { - String location = Utils.home()+"/state"; - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); - conf.persistenceManager = new LocalPersistence(location); - } - } - private static void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{ - Section authorizationSection = configurator.get("authorization"); - if (authorizationSection != null) { - - String provider = authorizationSection.get("provider"); - AuthorizationProvider authProvider; - if (provider!=null) { - try { - Object authProviderImpl = Class.forName(provider).newInstance(); - authProvider = AuthorizationProvider.class.cast(authProviderImpl); - }catch (Exception e) { - throw new Exception("ini file error: invalid provider type in \"authorization\" section", e); - } - } else - authProvider = new DefaultAuthorizationProvider(); - - - String type = authorizationSection.get("credentials.class"); - if (type ==null) - throw new Exception("ini file error: credentials type not found in \"authorization\" section"); - Credentials credentials; - try { - Object credentialsImpl = Class.forName(type).newInstance(); - credentials = Credentials.class.cast(credentialsImpl); - }catch (Exception e) { - throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e); - } - authorizationSection.to(credentials, "credentials."); - - authProvider.connect(credentials); - - conf.authorizationProvider = authProvider; - } - } } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 7d112a0..b7b5325 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -1,18 +1,26 @@ package org.gcube.smartgears.configuration.container; -import static org.gcube.smartgears.utils.Utils.*; - +import java.io.File; import java.io.InputStream; -import java.lang.reflect.Modifier; -import java.util.HashSet; -import java.util.ServiceLoader; -import java.util.Set; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.handlers.container.ContainerHandler; +import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; +import org.gcube.smartgears.handlers.container.lifecycle.ProfileContainerManager; +import org.gcube.smartgears.persistence.LocalPersistence; +import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; +import org.gcube.smartgears.security.AuthorizationProviderFactory; +import org.gcube.smartgears.security.Credentials; +import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory; import org.gcube.smartgears.utils.Utils; +import org.ini4j.Ini; +import org.ini4j.Profile.Section; /** * Binds {@link ContainerConfiguration}s to and from XML serialisations. @@ -22,31 +30,117 @@ import org.gcube.smartgears.utils.Utils; */ public class ContainerConfigurationBinder { - /** - * Returns a {@link ContainerConfiguration} from its XML serialisation. - * - * @param stream the serialisation - * @return the configuration - * @throws RuntimeException if the serialisation is invalid - */ - public ContainerConfiguration bind(InputStream stream) { + public ContainerConfiguration load(InputStream stream) { try { + Ini configurator = new Ini(stream); + ContainerConfiguration conf = new ContainerConfiguration(); - JAXBContext ctx = JAXBContext.newInstance(ContainerConfiguration.class); + Section nodeSection = configurator.get("node"); + if (nodeSection != null ) { + BaseConfiguration nodeConf = new BaseConfiguration(); + nodeSection.to(nodeConf); + conf.setBaseConfiguration(nodeConf); + } - ContainerConfiguration config = (ContainerConfiguration) ctx.createUnmarshaller().unmarshal(stream); + Section propertiesSection = configurator.get("properties"); + if (propertiesSection!=null) + conf.setProperties(propertiesSection.entrySet().stream() + .collect(Collectors.toMap(Entry::getKey, Entry::getValue))); + + Section siteSection = configurator.get("site"); + if (siteSection != null) { + Site siteConf = new Site(); + siteSection.to(siteConf); + conf.setSite(siteConf); + } + + initAuthorizationPart(configurator, conf); - return config; - - } catch (JAXBException e) { - - throw new RuntimeException("invalid container configuration", e); + initPersistencePart(configurator, conf); + + initProxyPart(configurator, conf); + + //TODO: find a solution for this shit + String location = Utils.home()+"/state"; + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + conf.setAccountingFallbackLocation(location); + // END Shit + + return conf; + }catch (Exception e) { + throw new RuntimeException(e); } - finally { + } + + private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section proxySection = configurator.get("proxy"); + if (proxySection != null) { + ProxyAddress proxyConf = new ProxyAddress(); + proxySection.to(proxyConf); + conf.setProxy(proxyConf); + } + } + + private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section persistenceSection = configurator.get("persistence"); + if (persistenceSection != null) { + String type = persistenceSection.get("class"); + if (type ==null) + throw new Exception("ini file error: type not found in \"persistence\" section"); + PersistenceWriter persistenceWriter; + try { + Object persistenceImpl = Class.forName(type).newInstance(); + persistenceWriter = PersistenceWriter.class.cast(persistenceImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e); + } + persistenceSection.to(persistenceWriter); + conf.setPersistenceManager(persistenceWriter); + } else { + String location = Utils.home()+"/state"; + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + conf.setPersistenceManager(new LocalPersistence(location)); + } + } + + private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + Section authorizationSection = configurator.get("authorization"); + if (authorizationSection != null) { - Utils.closeSafely(stream); + String provider = authorizationSection.get("factory"); + AuthorizationProviderFactory authProviderFactory; + if (provider!=null) { + try { + Object authProviderImpl = Class.forName(provider).newInstance(); + authProviderFactory = AuthorizationProviderFactory.class.cast(authProviderImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid provider type in \"authorization\" section", e); + } + } else + authProviderFactory = new DefaultAuthorizationProviderFactory(); + + + String type = authorizationSection.get("credentials.class"); + if (type ==null) + throw new Exception("ini file error: credentials type not found in \"authorization\" section"); + Credentials credentials; + try { + Object credentialsImpl = Class.forName(type).newInstance(); + credentials = Credentials.class.cast(credentialsImpl); + }catch (Exception e) { + throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e); + } + authorizationSection.to(credentials, "credentials."); + + AuthorizationProvider authProvider = authProviderFactory.connect(credentials); + + conf.setAuthorizationProvider(authProvider); } } @@ -57,45 +151,27 @@ public class ContainerConfigurationBinder { * @return the handlers * @throws RuntimeException if the serialisation is invalid */ - public ContainerHandlers bindHandlers(InputStream stream) { + public List bindHandlers(ClassLoader classloader) { - //collects handler classes - Set> classes = scanForConfigurationElements(); - - try { - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - return (ContainerHandlers) ctx.createUnmarshaller().unmarshal(stream); - - } catch (JAXBException e) { - - throw unchecked(e); - - } + LinkedList handlers = new LinkedList(); + + //ADDING BASE Handler (order is important) + handlers.add(new AccountingManager()); + handlers.add(new ProfileContainerManager()); + + handlers.addAll(scanForContainerHadlers(classloader)); + + return handlers; + } - private Set> scanForConfigurationElements() throws RuntimeException { - - @SuppressWarnings("all") - ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ContainerHandler.class); - - Set> scanned = new HashSet>(); - - for (ContainerHandler handler : handlerLoader) { - Class handlerClass = handler.getClass(); - if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT) - continue; - else - scanned.add(handlerClass); - } - - //add top-level configuration - scanned.add(ContainerHandlers.class); - - return scanned; + private List scanForContainerHadlers(ClassLoader classloader) throws RuntimeException { + + //TODO: scan for Container Handler + + return Collections.emptyList(); } } diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java deleted file mode 100644 index 73534b8..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerHandlers.java +++ /dev/null @@ -1,50 +0,0 @@ -package org.gcube.smartgears.configuration.container; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.smartgears.handlers.container.ContainerHandler; - -/** - * The {@link ContainerHandler}s that manage the application. - * - * @author Fabio Simeoni - * - */ -@XmlRootElement(name="handlers") -public class ContainerHandlers { - - @XmlAnyElement(lax=true) - List handlers = new ArrayList(); - - public ContainerHandlers() {} - - /** - * Returns the {@link ContainerHandler}s for the service. - * @return the lifecycle handlers - */ - public List get() { - return handlers; - } - - /** - * Sets the {@link ContainerHandler}s for the service. - * @param handlers the lifecycle handlers - * @return this configuration - */ - public ContainerHandlers set(ContainerHandler ... handlers) { - this.handlers = Arrays.asList(handlers); - return this; - } - - public void mergeWith(ContainerHandlers other){ - List handlers = other.get(); - for (ContainerHandler handler : handlers) - if (!this.get().contains(handler)) - this.get().add(handler); - } -} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java index a879731..019e2ab 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/AccountingManager.java @@ -5,8 +5,6 @@ package org.gcube.smartgears.handlers.container.lifecycle; import static org.gcube.smartgears.Constants.accounting_management; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.accounting.persistence.AccountingPersistenceFactory; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; @@ -16,7 +14,6 @@ import org.slf4j.LoggerFactory; /** * @author Luca Frosini (ISTI - CNR) */ -@XmlRootElement(name = accounting_management) public class AccountingManager extends ContainerHandler { private static Logger logger = LoggerFactory.getLogger(AccountingManager.class); diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java similarity index 97% rename from src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java rename to src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java index e420768..62b4a62 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java @@ -19,8 +19,6 @@ import static org.gcube.smartgears.lifecycle.container.ContainerState.active; import java.util.Collections; import java.util.concurrent.ScheduledFuture; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.events.Observes; import org.gcube.common.resources.gcore.HostingNode; import org.gcube.smartgears.configuration.Mode; @@ -52,10 +50,9 @@ import org.slf4j.LoggerFactory; * @author Fabio Simeoni * @see ProfileBuilder */ -@XmlRootElement(name = profile_management) -public class ProfileManager extends ContainerHandler { +public class ProfileContainerManager extends ContainerHandler { - private static Logger log = LoggerFactory.getLogger(ProfileManager.class); + private static Logger log = LoggerFactory.getLogger(ProfileContainerManager.class); private ContainerContext context; diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index c1622dd..537e650 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -83,7 +83,6 @@ public class ApplicationManager { registerObservers(); ApplicationHandlers handlers = provider().handlersFor(context); - handlers.validate(); ApplicationExtensions extensions = provider().extensionsFor(context); extensions.validate(); diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 4323232..f44ad3d 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -16,7 +16,6 @@ import java.util.Set; import org.gcube.common.events.Observes; import org.gcube.common.events.Observes.Kind; import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.configuration.container.ContainerHandlers; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.handlers.container.ContainerHandler; @@ -61,18 +60,15 @@ public class ContainerManager { saveContainerState(); - ContainerHandlers handlers = provider().containerHandlers(); + List handlers = provider().containerHandlers(); - log.trace("managing container lifecycle with {}", handlers.get()); + log.trace("managing container lifecycle with {}", handlers); - startHandlers(handlers.get()); + + startHandlers(handlers); context.lifecycle().moveTo(active); - - log.trace("loading keys for starting token ..."); - //loadKeyForToken(context.configuration().startTokens()); - log.trace("keys loaded for starting token ..."); - + return context; } catch(RuntimeException e) { @@ -103,10 +99,9 @@ public class ContainerManager { //List tokensToRemove = new ArrayList(); context.configuration().validate(); Set foundContexts; - - + try { - foundContexts = context.configuration().allowedContexts(); + foundContexts = context.configuration().authorizationProvider().getAllowedContexts(); } catch (Exception e) { log.error("error authorizing container",e); throw new RuntimeException("error authorizing container, moving the container to failed",e); diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index e51d90e..822d914 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -1,17 +1,12 @@ package org.gcube.smartgears.provider; -import static org.gcube.smartgears.Constants.application_handlers_file_name; import static org.gcube.smartgears.Constants.configuration_file_path; import static org.gcube.smartgears.Constants.container_configuraton_file_path; -import static org.gcube.smartgears.Constants.container_handlers_file_name; -import static org.gcube.smartgears.Constants.container_handlers_file_path; import static org.gcube.smartgears.Constants.container_profile_file_path; import static org.gcube.smartgears.Constants.default_extensions_file_path; -import static org.gcube.smartgears.Constants.default_handlers_file_path; import static org.gcube.smartgears.Constants.extensions_file_path; import static org.gcube.smartgears.Constants.ghn_home_env; import static org.gcube.smartgears.Constants.ghn_home_property; -import static org.gcube.smartgears.Constants.handlers_file_path; import static org.gcube.smartgears.Constants.library_configuration_file_path; import static org.gcube.smartgears.Constants.profile_file_path; @@ -19,21 +14,13 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.ObjectInputStream; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; +import java.util.List; import java.util.UUID; import javax.servlet.ServletContext; import org.gcube.common.events.Hub; import org.gcube.common.events.impl.DefaultHub; -import org.gcube.common.scan.ClasspathScanner; -import org.gcube.common.scan.ClasspathScannerFactory; -import org.gcube.common.scan.matchers.NameMatcher; -import org.gcube.common.scan.resources.ClasspathResource; import org.gcube.informationsystem.publisher.RegistryPublisherFactory; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.Mode; @@ -44,7 +31,6 @@ import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder; -import org.gcube.smartgears.configuration.container.ContainerHandlers; import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder; import org.gcube.smartgears.context.Properties; @@ -52,6 +38,7 @@ import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.DefaultApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.context.container.DefaultContainerContext; +import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; import org.gcube.smartgears.security.AuthorizationProvider; @@ -78,7 +65,7 @@ public class DefaultProvider implements Provider { protected DefaultProvider(File configFile) { this.configFile = configFile; } - + protected DefaultProvider(){}; @@ -87,18 +74,6 @@ public class DefaultProvider implements Provider { if(containerContext==null){ ContainerConfiguration configuration = containerConfiguration(); - - - /* - if (configuration.persistence()==null) { - String location = Utils.home()+"/state"; - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); - configuration.persistence(new LocalPersistence(location)); - - log.trace("setting persistence location for container @ {}",dir.getAbsolutePath()); - }*/ Hub hub = new DefaultHub(); @@ -128,17 +103,11 @@ public class DefaultProvider implements Provider { } @Override - public ContainerHandlers containerHandlers() { + public List containerHandlers() { try { - //TODO retrieve handler classes - - if (config == null) - throw new IllegalStateException("invalid distribution: cannot find " + container_handlers_file_path); - ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); - ContainerHandlers defaultHandlers = binder.bindHandlers(config); ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){ @@ -146,35 +115,7 @@ public class DefaultProvider implements Provider { currentClassLoader = currentClassLoader.getParent(); } - - try{ - if (currentClassLoader instanceof URLClassLoader){ - URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ; - - if (urls!=null && urls.length>0){ - ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet(Arrays.asList(urls))); - Collection resources = scanner.scan(new NameMatcher(container_handlers_file_name)); - - for (URL url: urls) - log.trace("URL: "+ url.toString()); - - if (resources==null || resources.isEmpty()) - log.info("no custom container handlers found in the classpath"); - - for (ClasspathResource res : resources){ - try{ - ContainerHandlers customHandlers= binder.bindHandlers(res.stream()); - defaultHandlers.mergeWith(customHandlers); - log.trace("container hadlers found in {}",res.name()); - }catch(Exception e){ - log.warn("error loading not default container handlers {}",res.name(),e); - } - } - } - } else log.info("this classloader is not instance of {} : ",URLClassLoader.class.getName(), currentClassLoader.getClass().getName()); - }catch(Exception e){ - log.warn("cannot load custom handlers for container from the root classloader",e); - } + List defaultHandlers = binder.bindHandlers(currentClassLoader); return defaultHandlers; @@ -250,15 +191,10 @@ public class DefaultProvider implements Provider { try { - // it's in a library, using - InputStream defaultHandlersStream = getClass().getResourceAsStream(default_handlers_file_path); - - if (defaultHandlersStream == null) - throw new IllegalStateException("invalid distribution: cannot find " + default_handlers_file_path); ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - ApplicationHandlers defaultHandlers = binder.bindHandlers(defaultHandlersStream); + //searching for smartegars related application handlers in the common classloader ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); @@ -267,40 +203,8 @@ public class DefaultProvider implements Provider { currentClassLoader = currentClassLoader.getParent(); } - - try{ - if (currentClassLoader instanceof URLClassLoader){ - URL[] urls = ((URLClassLoader) currentClassLoader).getURLs() ; - - if (urls!=null && urls.length>0){ - ClasspathScanner scanner = ClasspathScannerFactory.scanner(new HashSet(Arrays.asList(urls))); - Collection resources = scanner.scan(new NameMatcher(application_handlers_file_name)); - if (resources==null || resources.isEmpty()) - log.info("no custom smartgears related application handlers found in the classpath"); - - for (ClasspathResource res : resources){ - try{ - ApplicationHandlers customHandlers= binder.bindHandlers(res.stream()); - defaultHandlers.mergeWith(customHandlers); - log.trace("application hadlers found in {}",res.name()); - }catch(Exception e){ - log.warn("error loading smartgears related application handlers {}",res.name(),e); - } - } - } - } - }catch(Exception e){ - log.warn("cannot load smartgears related handlers for application from the root classloader",e); - } - - InputStream appSpecificHandlersStream = context.application().getResourceAsStream(handlers_file_path); - - if (appSpecificHandlersStream !=null ){ - defaultHandlers.mergeWith(binder.bindHandlers(appSpecificHandlersStream)); - log.trace("{} uses default lifecycle with app spceific handler as it includes {}", context.name(), handlers_file_path); - } else - log.trace("{} uses the default lifecycle as it does not include {}", context.name(), handlers_file_path); - + ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader); + return defaultHandlers; @@ -393,9 +297,9 @@ public class DefaultProvider implements Provider { private ContainerConfiguration containerConfiguration() { if (configFile==null) { - + String home = Utils.home(); - + if (home == null) throw new IllegalStateException("invalid node configuration: the environment variable " + ghn_home_env + " or the system property " + ghn_home_property + " must be defined"); @@ -407,7 +311,7 @@ public class DefaultProvider implements Provider { configFile = new File(homeDir,container_configuraton_file_path); - + log.trace("reading container configuration @ {} ", configFile.getAbsolutePath()); } @@ -416,11 +320,11 @@ public class DefaultProvider implements Provider { ContainerConfiguration configuration; try (InputStream stream = new FileInputStream(configFile)){ - configuration= ContainerConfiguration.load(stream); + configuration= new ContainerConfigurationBinder().load(stream); }catch (Exception e) { - throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid"); + throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid", e); } - + return configuration; } diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index ba3a873..113d389 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -1,14 +1,16 @@ package org.gcube.smartgears.provider; +import java.util.List; + import javax.servlet.ServletContext; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.container.ContainerHandlers; import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.security.AuthorizationProvider; /** @@ -37,7 +39,7 @@ public interface Provider { * Returns the handlers associated with the container. * @return the handlers */ - ContainerHandlers containerHandlers(); + List containerHandlers(); /** diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index afe8b11..abafa2d 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -4,7 +4,5 @@ import java.util.Set; public interface AuthorizationProvider { - void connect(Credentials credentials) throws Exception; - Set getAllowedContexts(); } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java new file mode 100644 index 0000000..c18bcd7 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java @@ -0,0 +1,7 @@ +package org.gcube.smartgears.security; + +public interface AuthorizationProviderFactory { + + T connect(Credentials credentials); + +} diff --git a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java index 3c8a5ab..ac45581 100644 --- a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java +++ b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java @@ -10,6 +10,9 @@ public class SimpleCredentials implements Credentials{ @NotNull @NotEmpty String secret; + + @NotNull @NotEmpty + String endpoint; public String getClientID() { return clientID; @@ -17,6 +20,14 @@ public class SimpleCredentials implements Credentials{ public void setClientID(String clientID) { this.clientID = clientID; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; } public String getSecret() { diff --git a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java similarity index 76% rename from src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java rename to src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index dd6a2e9..686426e 100644 --- a/src/main/java/org/gcube/smartgears/security/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -1,5 +1,6 @@ -package org.gcube.smartgears.security; +package org.gcube.smartgears.security.defaults; +import java.net.URL; import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -11,6 +12,8 @@ import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.smartgears.security.AuthorizationProvider; +import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,20 +21,20 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { private static Logger LOG = LoggerFactory.getLogger(DefaultAuthorizationProvider.class); - private SimpleCredentials credentials; - private KeycloakClient client = KeycloakClientFactory.newInstance(); - @Override - public void connect(Credentials credentials) { - this.credentials = (SimpleCredentials)credentials; + private SimpleCredentials credentials; + + public DefaultAuthorizationProvider(SimpleCredentials credentials) { + this.credentials = credentials; } + @Override public Set getAllowedContexts() { Set contexts = new HashSet(); try { - TokenResponse response = client.queryOIDCToken(credentials.getClientID(), credentials.getSecret()); + TokenResponse response = client.queryOIDCToken(new URL(credentials.getEndpoint()), credentials.getClientID(), credentials.getSecret()); Map resourceAccess = ModelUtils.getAccessTokenFrom(response).getResourceAccess(); for (String context : resourceAccess.keySet()) { try { diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java new file mode 100644 index 0000000..9903c0d --- /dev/null +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java @@ -0,0 +1,17 @@ +package org.gcube.smartgears.security.defaults; + +import org.gcube.smartgears.security.AuthorizationProviderFactory; +import org.gcube.smartgears.security.Credentials; +import org.gcube.smartgears.security.SimpleCredentials; + +public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory{ + + @Override + public DefaultAuthorizationProvider connect(Credentials credentials) { + if (!SimpleCredentials.class.isInstance(credentials)) + throw new IllegalArgumentException("invalid credential type passed"); + return new DefaultAuthorizationProvider((SimpleCredentials)credentials); + } + + +} diff --git a/src/main/resources/META-INF/container-handlers.xml b/src/main/resources/META-INF/container-handlers.xml deleted file mode 100644 index 9884b0e..0000000 --- a/src/main/resources/META-INF/container-handlers.xml +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/src/main/resources/META-INF/default-handlers.xml b/src/main/resources/META-INF/default-handlers.xml deleted file mode 100644 index d6a1181..0000000 --- a/src/main/resources/META-INF/default-handlers.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler deleted file mode 100644 index 977cf56..0000000 --- a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler +++ /dev/null @@ -1,4 +0,0 @@ -org.gcube.smartgears.handlers.application.lifecycle.ProfileManager -org.gcube.smartgears.handlers.application.request.RequestValidator -org.gcube.smartgears.handlers.application.request.RequestAccounting -org.gcube.smartgears.handlers.application.request.RequestContextRetriever \ No newline at end of file diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler deleted file mode 100644 index 5c13143..0000000 --- a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler +++ /dev/null @@ -1,2 +0,0 @@ -org.gcube.smartgears.handlers.container.lifecycle.ProfileManager -org.gcube.smartgears.handlers.container.lifecycle.AccountingManager \ No newline at end of file diff --git a/src/test/java/app/Request.java b/src/test/java/app/Request.java deleted file mode 100644 index 99eae31..0000000 --- a/src/test/java/app/Request.java +++ /dev/null @@ -1,187 +0,0 @@ -package app; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.logging.Logger; - -import javax.ws.rs.HttpMethod; -import javax.ws.rs.WebApplicationException; -import javax.ws.rs.client.Client; -import javax.ws.rs.client.ClientBuilder; -import javax.ws.rs.client.Invocation.Builder; - -import org.gcube.common.authorization.library.provider.AuthorizationProvider; -import org.gcube.common.authorization.library.provider.UserInfo; -import org.gcube.common.authorization.library.utils.Caller; -import org.gcube.smartgears.extensions.HttpExtension.Method; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.client.ClientResponse; -import org.glassfish.jersey.logging.LoggingFeature; - -import utils.TestUtils; - -public class Request { - - private String path=""; - private String scope = TestUtils.scope; - - //private OutBoundHeaders headers = new OutBoundHeaders(); - private String method = HttpMethod.GET; - private String body = null; - private boolean logged = false; - Map> headers = new HashMap<>(); - - public static Request request() { - return new Request(); - } - - private Request() { - - } - - public Request at(String path) { - this.path=path; - return this; - } - - public Request logging() { - logged=true; - return this; - } - - public Request inScope(String scope) { - this.scope=scope; - return this; - } - - public Request with(String body) { - this.body=body; - return this; - } - - public Request with(String name, String value) { - this.headers.put(name, Collections.singletonList(value)); - return this; - } - - public Request using(Method method) { - this.method=method.getValue(); - return this; - } - - public String path() { - return path; - } - - public String body() { - return body; - } - - public String method() { - return method; - } - - public String scope() { - return scope; - } - - ClientResponse make(final int port) { - - - // we make a scoped call in a separate thread, with which we then synchronize for completion. - // this helps isolate the caller's thread (Main normally) from the app's thread, - // starting with the scope itself. - final CountDownLatch latch = new CountDownLatch(1); - - class Box { - - volatile WebApplicationException failure; - volatile ClientResponse response; - - } - - final Box box = new Box(); - - new Thread() { - - public void run() { - - AuthorizationProvider.instance.set(new Caller(new UserInfo("test", new ArrayList()),"DEFAULT")); - - try { - - ClientConfig config = new ClientConfig(); - - - - - Client client = ClientBuilder.newClient(); - - - if (logged) - client.register(new LoggingFeature(Logger.getLogger(getClass().getName()))); - - Builder builder = client.target(address(path,port)).request(); - builder.header("gcube-scope", scope); - - - - for (Entry> header : headers.entrySet()) - for (Object value : header.getValue()) - builder.header(header.getKey(), value); - - if (method.equals(HttpMethod.DELETE)) - builder.delete(); - else { - - System.err.println("making request @ "+address(path,port)); - - ClientResponse response = builder.method(method,ClientResponse.class); - - //throws an exception if there response has error status - if (response.getStatus()>300) - throw new WebApplicationException(response.getStatus()); - - box.response=response; - } - - - } catch (WebApplicationException t) { - box.failure=t; - } - - latch.countDown(); - }; - }.start(); - - try { - - if (!latch.await(2000, TimeUnit.MILLISECONDS)) - throw new RuntimeException("application has not responded in time"); - - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - - if (box.failure !=null) - throw box.failure; - - else - return box.response; - - } - - private String address(String path, long port) { - - path = (path.isEmpty() || path.startsWith("/"))?path:"/"+path; - - return "http://localhost:" + port+ "/" + TestUtils.context_root+path; - } - -} diff --git a/src/test/java/app/SomeApp.java b/src/test/java/app/SomeApp.java deleted file mode 100644 index 9e1483a..0000000 --- a/src/test/java/app/SomeApp.java +++ /dev/null @@ -1,437 +0,0 @@ -package app; - -import static org.gcube.smartgears.Constants.configuration_file_path; -import static org.gcube.smartgears.Constants.extensions_file_path; -import static org.gcube.smartgears.Constants.ghn_home_property; -import static org.gcube.smartgears.Constants.handlers_file_path; -import static utils.TestUtils.context_root; -import static utils.TestUtils.context_root_path; -import static utils.TestUtils.location; -import static utils.TestUtils.servlet_name; - -import java.io.File; -import java.io.InputStream; - -import org.apache.catalina.Wrapper; -import org.apache.catalina.core.StandardContext; -import org.apache.catalina.startup.Tomcat; -import org.apache.commons.io.FileUtils; -import org.apache.tomcat.util.scan.StandardJarScanner; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; -import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.managers.ContainerManager; -import org.gcube.smartgears.provider.ProviderFactory; -import org.glassfish.jersey.client.ClientResponse; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.StringAsset; -import org.jboss.shrinkwrap.api.exporter.ZipExporter; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.jboss.shrinkwrap.impl.base.path.BasicPath; - -import utils.TestProvider; -import utils.TestUtils; - -/** - * Simulates a single-servlet application to be transformed into a gCube resource. - *

- *

    - *
  • uses a default configuration that can be customised (cf. {@link #configuration()}); - *
  • can be configured with the default handlers (cf. {@link #useDefaultHandlers()}) or custom ones ( - * {@link #handlers()}), including those that are not deployable through standard means, such as mocks ( - * {@link #bypassHandlerDeployment()}; - *
  • can be started to have a default behaviour when called, ({@link #start()}) or else a custom behaviour ( - * {@link #startWith(Runnable)}; - *
- * can be called in a default scope ({@link #call()} or in a specific scope ({@link #callIn(String)}). Calls are blocking but always - * configured and executed in a separate thread; - * - * @author Fabio Simeoni - * - */ -public class SomeApp { - - private final Tomcat tomcat = new Tomcat(); - - private WebArchive war = defaultWar(); - - private ContainerConfiguration containerConfiguration; - private ApplicationConfiguration configuration; - private ApplicationHandlers handlers = new ApplicationHandlers(); - private ApplicationExtensions extensions = new ApplicationExtensions(); - private TestProvider provider = new TestProvider(new File("src/test/resources/test-configuration.ini")); - private boolean deployHandlers = true; - private boolean deployExtensions = true; - private boolean deployConfiguration = true; - private boolean clean=true; - - public SomeApp() { - - if (ContainerManager.instance!=null) - ContainerManager.instance.stop(true); - - tomcat.getConnector().setPort(0); - tomcat.setBaseDir(location); - - System.setProperty(ghn_home_property,location); - - containerConfiguration = defaultContainerConfiguration(); - configuration = defaultConfiguration(); - } - - /** - * Sets a {@link TestProvider} to resolve dependencies at runtime. - * - * @param provider the provider - */ - public void set(TestProvider provider) { - this.provider = provider; - } - - /** - * Runs the test with the state left by previous run. - *

- * Use only within a single test! - */ - public void dirtyRun() { - this.clean = false; - } - - /** - * Returns the configuration of the application. - *

- * The initial configuration is based on defaults, but can be changed and extended. - * - * @return the configuration - */ - public ApplicationConfiguration configuration() { - return configuration; - } - - /** - * Returns the configuration of the containerConfiguration. - *

- * The initial configuration is based on defaults, but can be changed and extended. - * - * @return the configuration - */ - public ContainerConfiguration containerConfiguration() { - return containerConfiguration; - } - - /** - * Returns the handlers that manage the application, none by default. - * - * @return the handlers - */ - public ApplicationHandlers handlers() { - return handlers; - } - - /** - * Avoids deployment of the configured handlers in the application's WAR. - *

- * The handlers will instead be directly available at runtime. - */ - public void bypassHandlerDeployment() { - - provider.use(handlers()); - deployHandlers = false; - } - - - /** - * Avoids resource configuration deployment. - */ - public void asExternal() { - - configuration.context(context_root_path); - containerConfiguration.app(configuration); - - bypassConfigurationDeployment(); - bypassExtensionsDeployment(); - bypassHandlerDeployment(); - } - - /** - * Avoids resource configuration deployment. - */ - public void withExternal(ApplicationConfiguration config) { - - config.context(context_root_path); - - containerConfiguration.app(config.context()).merge(config); - } - - public void bypassConfigurationDeployment() { - - deployConfiguration = false; - - } - - - public void usePublisher(ScopedPublisher publisher) { - - provider.use(publisher); - } - - /** - * Uses default handlers. - */ - public void useDefaultHandlers() { - - deployHandlers = false; - } - - - /** - * Returns the extensions of the application, none by default. - * - * @return the handlers - */ - public ApplicationExtensions extensions() { - return extensions; - } - - /** - * Uses default extensions. - */ - public void useDefaultExtensions() { - - deployExtensions = false; - } - - /** - * Avoids deployment of the configured extensions in the application's WAR. - *

- * The extensions will instead be directly available at runtime. - */ - public void bypassExtensionsDeployment() { - - provider.use(extensions()); - deployExtensions = false; - } - - /** - * Starts the application. - * - * @return the context of the application - */ - public ApplicationContext start() { - - return startWith(new Runnable() { - - @Override - public void run() { - System.err.println("test servlet invoked with no particular task"); - } - }); - } - - /** - * Starts the application, injecting test logic in its single servlet - * - * @param test test logic - * @return the context of the application - */ - public ApplicationContext startWith(Runnable test) { - - // install provider - ProviderFactory.testProvider(provider); - - if (clean) - cleanupInstallation(); - - - if (deployConfiguration) - deployConfiguration(); - - if (deployHandlers) - deployHandlers(); - - if (deployExtensions) - deployExtensions(); - - try { - - System.err.println("deploying with " + war.toString(true)); - - StandardContext ctx = (StandardContext) tomcat.addWebapp(context_root_path, warFile().getAbsolutePath()); - - // tells tomcat to look also for exploded directories such as this project's (finds initializer) - ((StandardJarScanner) ctx.getJarScanner()).setScanAllDirectories(true); - - //this starts webapp and always comes back - tomcat.start(); - - ApplicationContext context = provider.context; - - if (context==null) - throw new RuntimeException("app failed @ startup"); - - Wrapper webapp = (Wrapper) tomcat.getHost().findChild(context_root_path).findChild(servlet_name); - - if (webapp!=null) { - - webapp.setServlet(new TestServlet(test)); - - //context.container().configuration().port(port()); - - containerConfiguration = context.container().configuration(); - } - - return context; - - } catch (Exception e) { - throw new RuntimeException(e); - } - - } - - /** - * Retuens true if the application was successfully start in the container. - * - * @return true if the application was successfully start in the container - */ - public boolean isActive() { - return tomcat.getHost().findChild("/" + context_root).findChild(servlet_name) != null; - } - - /** - * Makes a request to the application. - */ - - public String send(Request call) { - return (String) call.make(port()).getEntity(); - } - - /** - * Makes a request to the application. - */ - - public ClientResponse httpSend(Request call) { - return call.make(port()); - } - - - /** - * Stops the application - */ - public void stop() { - - try { - tomcat.stop(); - tomcat.destroy(); - - } catch (Exception e) { - System.err.println("WARNING: could not clearly stop container:"); - e.printStackTrace(); - } - } - - public File containerConfigurationFile() { - - return new File(location,Constants.container_configuraton_file_path); - } - // helpers - - - - /** - * Includes the configuration in the application's WAR. - */ - private void deployConfiguration() { - - String xml = TestUtils.bind(configuration()); - - System.err.println("deploying with configuration:\n" + xml); - - war.addAsWebResource(new StringAsset(xml), new BasicPath(configuration_file_path)); - } - - /** - * Includes the handlers in the application's WAR. - */ - private void deployHandlers() { - - String xml = TestUtils.bind(handlers()); - - System.err.println("deploying with handlers:\n" + xml); - - war.addAsWebResource(new StringAsset(xml), new BasicPath(handlers_file_path)); - } - - /** - * Includes the extensions in the application's WAR. - */ - private void deployExtensions() { - - String xml = TestUtils.bind(extensions()); - - System.err.println("deploying with extensions:\n" + xml); - - war.addAsWebResource(new StringAsset(xml), new BasicPath(extensions_file_path)); - } - - private File warFile() { - - File warFile = new File(location, "test.war"); - - if (warFile.exists() && !warFile.delete()) - System.out.println("could not delete old deployment");; // seems safer than plain overwrite to avoid war corruption - - war.as(ZipExporter.class).exportTo(warFile, true); - - return warFile; - - } - - private WebArchive defaultWar() { - - WebArchive war = ShrinkWrap.create(WebArchive.class); - war.setWebXML(new File("src/test/java/app/web.xml")); - return war; - - } - - private ApplicationConfiguration defaultConfiguration() { - - return new DefaultApplicationConfiguration().serviceClass("test-class").name("test-app").version("1.0"); - - } - - private ContainerConfiguration defaultContainerConfiguration() { - - InputStream is = SomeApp.class.getResourceAsStream("/test-configuration.ini"); - - return ContainerConfiguration.load(is); - - } - - public int port() { - return tomcat.getConnector().getLocalPort(); - } - - private void cleanupInstallation() { - - System.out.println("cleaning installation in location "+location); - - File installation = new File(location); - - if (installation.exists()) - try { - FileUtils.deleteDirectory(installation); - } - catch(Exception e) { - throw new RuntimeException(e); - } - - installation.mkdirs(); - - } -} diff --git a/src/test/java/app/TestServlet.java b/src/test/java/app/TestServlet.java deleted file mode 100644 index b74bf33..0000000 --- a/src/test/java/app/TestServlet.java +++ /dev/null @@ -1,30 +0,0 @@ -package app; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.annotation.WebServlet; -import javax.servlet.http.HttpServlet; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - - - -@WebServlet(name = "test", urlPatterns = "/test") -public class TestServlet extends HttpServlet { - - private static final long serialVersionUID = 1L; - - private Runnable test; - - public TestServlet(Runnable test) { - this.test=test; - } - - @Override - protected void doGet(HttpServletRequest request, - HttpServletResponse response) throws ServletException, IOException { - - test.run(); - } -} diff --git a/src/test/java/app/web.xml b/src/test/java/app/web.xml deleted file mode 100644 index 5199029..0000000 --- a/src/test/java/app/web.xml +++ /dev/null @@ -1,15 +0,0 @@ - - - test-app - - - test - app.TestServlet - - - - test - /* - - - \ No newline at end of file diff --git a/src/test/java/test/BinderTest.java b/src/test/java/test/BinderTest.java new file mode 100644 index 0000000..8c059c1 --- /dev/null +++ b/src/test/java/test/BinderTest.java @@ -0,0 +1,20 @@ +package test; + +import java.io.InputStream; + +import org.gcube.smartgears.configuration.container.ContainerConfiguration; +import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder; +import org.junit.Test; + +public class BinderTest { + + + @Test + public void bindConfig() throws Exception { + + InputStream stream = BinderTest.class.getResourceAsStream("/container.ini"); + + ContainerConfiguration conf = new ContainerConfigurationBinder().load(stream); + System.out.println(conf.toString()); + } +} diff --git a/src/test/java/test/application/AppLifecycleTest.java b/src/test/java/test/application/AppLifecycleTest.java deleted file mode 100644 index 8d339ea..0000000 --- a/src/test/java/test/application/AppLifecycleTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package test.application; - -import static org.junit.Assert.*; - -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; -import org.gcube.smartgears.lifecycle.application.ApplicationState; -import org.gcube.smartgears.lifecycle.container.ContainerState; -import org.junit.Test; - -import app.SomeApp; - -public class AppLifecycleTest { - - @Test - public void applicationGoesDownIfContainerDoes() { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()); - - ApplicationContext actx = app.start(); - - assertEquals(ApplicationState.active,actx.lifecycle().state()); - - ContainerContext ctx = actx.container(); - - assertEquals(ContainerState.active,ctx.lifecycle().state()); - - ctx.lifecycle().moveTo(ContainerState.stopped); - - assertEquals(ApplicationState.stopped,actx.lifecycle().state()); - } - -} diff --git a/src/test/java/test/application/CallValidationTest.java b/src/test/java/test/application/CallValidationTest.java deleted file mode 100644 index e2e8d5b..0000000 --- a/src/test/java/test/application/CallValidationTest.java +++ /dev/null @@ -1,214 +0,0 @@ -package test.application; - -import static app.Request.request; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.fail; -import static org.gcube.smartgears.handlers.application.request.RequestError.application_failed_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.request_not_authorized_error; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.stopped; -import static utils.TestUtils.scope; - -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import javax.ws.rs.WebApplicationException; - -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.configuration.application.Exclude; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; -import org.gcube.smartgears.handlers.application.request.RequestValidator; -import org.junit.Test; - -import app.SomeApp; - - -public class CallValidationTest { - - - @Test - public void rejectsCallsWhenServiceIsInactive() { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - - Runnable test = new Runnable() { - - @Override - public void run() { - fail("call should have been rejected"); - } - }; - - ApplicationContext context = app.startWith(test); - - context.lifecycle().moveTo(stopped); - - try { - app.send(request()); - } - catch(WebApplicationException e) { - assertEquals(application_unavailable_error.code(), e.getResponse().getStatus()); - } - - - context.lifecycle().moveTo(failed); - - try { - app.send(request()); - } - catch(WebApplicationException e) { - assertEquals(application_failed_error.code(), e.getResponse().getStatus()); - - } - - } - - @Test - public void rejectsCallsWithoutScope() throws Throwable { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - app.start(); - - try { - app.send(request().inScope(null));; //call in no scope - fail(); - } - catch(WebApplicationException e) { - assertEquals(request_not_authorized_error.code(), e.getResponse().getStatus()); - } - - } - - @Test - public void rejectsCallsWithBadScope() throws Throwable { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - app.start(); - - try { - app.send(request().inScope("/bad/scope")); //call in no scope - fail(); - } - catch(WebApplicationException e) { - assertEquals(invalid_request_error.code(), e.getResponse().getStatus()); - } - - } - - @Test - public void propagatesScope() throws Throwable { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - Runnable test = new Runnable() { - - @Override - public void run() { - assertEquals(scope,SecurityTokenProvider.instance.get()); - } - }; - - app.startWith(test); - - app.send(request()); - - } - - @Test - public void respectsAllExcludeWildCard() throws Throwable { - - SomeApp app = new SomeApp(); - - app.configuration().excludes().add(new Exclude(Constants.WILDCARD)); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - final CountDownLatch latch = new CountDownLatch(1); - - Runnable test = new Runnable() { - - @Override - public void run() { - latch.countDown(); - } - }; - - app.startWith(test); - - app.send(request().inScope(null)); - - latch.await(500,TimeUnit.MILLISECONDS); - - } - - @Test - public void respectsExcludeWildCard() throws Throwable { - - SomeApp app = new SomeApp(); - - app.configuration().excludes().add(new Exclude("/path"+Constants.WILDCARD)); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - final CountDownLatch latch = new CountDownLatch(1); - - Runnable test = new Runnable() { - - @Override - public void run() { - latch.countDown(); - } - }; - - app.startWith(test); - - app.send(request().at("path/test").inScope(null)); - - latch.await(500,TimeUnit.MILLISECONDS); - - } - - - @Test - public void respectsExactExclude() throws Throwable { - - SomeApp app = new SomeApp(); - - app.configuration().excludes().add(new Exclude("/path")); - - app.handlers().set(new ProfileManager()).set(new RequestValidator()); - - final CountDownLatch latch = new CountDownLatch(1); - - Runnable test = new Runnable() { - - @Override - public void run() { - latch.countDown(); - } - }; - - app.startWith(test); - - app.send(request().at("path").inScope(null)); - - latch.await(500,TimeUnit.MILLISECONDS); - - } - -} diff --git a/src/test/java/test/application/ConfigurationTest.java b/src/test/java/test/application/ConfigurationTest.java deleted file mode 100644 index b9b84a3..0000000 --- a/src/test/java/test/application/ConfigurationTest.java +++ /dev/null @@ -1,112 +0,0 @@ -package test.application; - -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; - -import java.io.ByteArrayInputStream; - -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.configuration.application.Include; -import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.junit.Test; - -public class ConfigurationTest { - - @Test - public void configurationBinds() throws Exception { - - String xml = "" + - "name" + - "class" + - "version" + - "desc" + - "start/scope"+ - "another/start/scope"+ - "/pathBis" + - "" + - ""; - - - ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - - ApplicationConfiguration bound = binder.bind(new ByteArrayInputStream(xml.getBytes())); - - - System.out.println(bound); - - assertEquals(sampleConfiguration(),bound); - - } - - - @Test - public void extensionsBind() throws Exception { - - String xml = "" + - "" + - ""; - - - ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - - ApplicationExtensions bound = binder.bindExtensions(new ByteArrayInputStream(xml.getBytes())); - - assertNotNull(bound.extensions()); - assertEquals(1,bound.extensions().size()); - - ApplicationExtension ext = bound.extensions().get(0); - assertEquals("custom",ext.name()); - assertEquals("custom",ext.mapping()); - - - } - - - /*@Test - public void configurationsMerge() throws Exception { - - ApplicationConfiguration original = sampleConfiguration(); - - ApplicationConfiguration one = sampleConfiguration(); - - ApplicationConfiguration two = new DefaultApplicationConfiguration(); - two.mode(Mode.online); - two.persistence(new DefaultPersistence(new File(".").getAbsolutePath())); - two.startScopes("yet/another/one"); - - one.merge(two); - - assertEquals(one.mode(), two.mode()); - assertEquals(one.name(), original.name()); - assertEquals(one.persistence(), two.persistence()); - - Set merged = new HashSet<>(original.startScopes()); - - merged.addAll(two.startScopes()); - - assertEquals(merged,one.startScopes()); - - }*/ - - //helpers - - private ApplicationConfiguration sampleConfiguration() { - - - return new DefaultApplicationConfiguration() - .context("ctx") - .name("name") - .serviceClass("class") - .includes(new Include("/pathBis")) - .version("version") - .description("desc") - .persistence(new LocalPersistence("target")); - - } - - -} diff --git a/src/test/java/test/application/ControllerTest.java b/src/test/java/test/application/ControllerTest.java deleted file mode 100644 index 13fcf34..0000000 --- a/src/test/java/test/application/ControllerTest.java +++ /dev/null @@ -1,288 +0,0 @@ -package test.application; - -import static app.Request.request; -import static org.gcube.smartgears.Constants.accept; -import static org.gcube.smartgears.Constants.allow; -import static org.gcube.smartgears.Constants.content_type; -import static org.gcube.smartgears.extensions.ApiResource.handles; -import static org.gcube.smartgears.extensions.ApiResource.method; -import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; -import static org.gcube.smartgears.extensions.HttpExtension.Method.POST; -import static org.gcube.smartgears.extensions.HttpExtension.Method.PUT; -import static org.gcube.smartgears.handlers.application.request.RequestError.incoming_contenttype_unsupported_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.method_unsupported_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.outgoing_contenttype_unsupported_error; -import static org.gcube.smartgears.handlers.application.request.RequestError.resource_notfound_error; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.ws.rs.WebApplicationException; - -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.extensions.ApiResource; -import org.gcube.smartgears.extensions.ApiSignature; -import org.gcube.smartgears.extensions.HttpController; -import org.gcube.smartgears.extensions.HttpExtension; -import org.glassfish.jersey.client.ClientResponse; -import org.junit.Test; - -import app.Request; -import app.SomeApp; - -public class ControllerTest { - - String name = "name"; - String extension_path = "/ext"; - String extension_mapping = "/ext/*"; - String resource_path = "/resource"; - - @Test - public void dispatchesToResource() { - - // returns a given type - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain")); - - // requires same type - Request request = request().at(resource()).with(accept, "text/plain"); - - SomeApp app = startAppWith(signature); - - app.send(request); - } - - @Test - public void toleratesTrainingSlashes() { - - // returns a given type - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain")); - - // requires same type - Request request = request().at(resource()).with(accept, "text/plain"); - - SomeApp app = startAppWith(signature); - - app.send(request); - } - - @Test - public void handlesUnknownResources() { - - ApiSignature signature = handles(resource_path); - - // points to not existing resource - Request request = request().at(resource() + "/bad"); - - SomeApp app = startAppWith(signature); - - try { - app.send(request); - fail(); - } catch (WebApplicationException e) { - assertEquals(resource_notfound_error.code(), e.getResponse().getStatus()); - } - } - - @Test - public void handlesUnsupportedMethods() { - - ApiSignature signature = handles(resource_path).with(method(GET)).with(method(PUT)); - - Request request = request().at(resource()).using(POST); - - SomeApp app = startAppWith(signature); - - try { - app.send(request); - fail(); - } catch (WebApplicationException e) { - assertEquals(method_unsupported_error.code(), e.getResponse().getStatus()); - assertNotNull(e.getResponse().getHeaders().toString(),e.getResponse().getHeaders().get(allow)); - } - } - - @Test - public void enforcesAcceptHeaders() { - - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain")); - - Request request = request().at(resource()).with(accept, "text/xml"); - - SomeApp app = startAppWith(signature); - - try { - app.send(request); - fail(); - } catch (WebApplicationException e) { - assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); - - } - } - - @Test - public void enforcesAcceptHeadersEvenWhenResourceDeclaresNone() { - - ApiSignature signature = handles(resource_path).with(method(GET)); - - Request request = request().at(resource()).with(accept, "text/xml"); - - SomeApp app = startAppWith(signature); - - try { - app.send(request); - fail(); - } catch (WebApplicationException e) { - assertEquals(outgoing_contenttype_unsupported_error.code(), e.getResponse().getStatus()); - } - } - - @Test - public void enforcesMultiValuedAcceptHeader() { - - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain")); - - Request request = request().at(resource()).with(accept, "text/xml").with(accept,"text/plain"); - - SomeApp app = startAppWith(signature); - - app.send(request); - - } - - @Test - public void setsContentTypeIfUnsetAndUnambiguous() { - - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain")); - - Request request = request().at(resource()).with(accept, "text/plain"); - - SomeApp app = startAppWith(signature); - - ClientResponse response = app.httpSend(request); - - assertTrue(response.getHeaders().get(content_type).get(0).contains("text/plain")); - } - - @Test - public void doesntSetContentTypeIfUnsetButAmbiguous() { - - ApiSignature signature = handles(resource_path).with(method(GET).produces("text/plain","text/xml")); - - Request request = request().at(resource()).with(accept, "text/plain"); - - SomeApp app = startAppWith(signature); - - ClientResponse response = app.httpSend(request); - - System.out.println(response.getHeaders()); - - assertNull(response.getHeaders().get(content_type)); - - } - - - @Test - public void enforcesMultiValuedContentTypeHeader() { - - ApiSignature signature = handles(resource_path).with(method(POST).accepts("application/xml")); - - Request request = request().at(resource()).using(POST).with(content_type, "text/xml").with(content_type,"text/plain"); - - SomeApp app = startAppWith(signature); - - try { - app.send(request); - fail(); - } catch (WebApplicationException e) { - assertEquals(incoming_contenttype_unsupported_error.code(), e.getResponse().getStatus()); - } - } - - @Test - public void acceptsContentTypeHeadersWhenResourceDeclaresNone() { - - ApiSignature signature = handles(resource_path).with(method(POST)); - - Request request = request().at(resource()).using(POST).with(content_type, "text/xml"); - - SomeApp app = startAppWith(signature); - - app.httpSend(request); - - } - - - - ///////////////////////////////// helpers - - private String resource() { - return Constants.root_mapping + extension_path + resource_path; - } - - SomeApp startAppWith(ApiSignature signature) { - - SomeApp app = new SomeApp(); - - app.extensions().set(controllerWith(signature)); - - app.bypassExtensionsDeployment(); - app.bypassHandlerDeployment(); - - app.start(); - - return app; - } - - - - @SuppressWarnings("serial") - HttpExtension controllerWith(final ApiSignature signature) { - return new HttpController(name, extension_mapping) { - - { - addResources(new ApiResource(signature) { - - @Override - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, - IOException { - if (!supports(Method.valueOf(req.getMethod()))) - super.doGet(req, resp); - else - resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping()); - } - - @Override - public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, - IOException { - if (!supports(Method.valueOf(req.getMethod()))) - super.doPost(req, resp); - else - resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping()); - } - - @Override - public void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, - IOException { - if (!supports(Method.valueOf(req.getMethod()))) - super.doPut(req, resp); - else - resp.getWriter().write(req.getMethod() + " invoked @ " + signature.mapping()); - } - - }); - } - - @Override - public String toString() { - return "SUT controller"; - } - }; - } -} diff --git a/src/test/java/test/application/ExtensionsTest.java b/src/test/java/test/application/ExtensionsTest.java deleted file mode 100644 index 59b86cd..0000000 --- a/src/test/java/test/application/ExtensionsTest.java +++ /dev/null @@ -1,184 +0,0 @@ -package test.application; - -import static app.Request.request; -import static junit.framework.Assert.assertEquals; -import static junit.framework.Assert.assertNotNull; -import static junit.framework.Assert.fail; -import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed; - -import java.io.IOException; - -import javax.servlet.ServletException; -import javax.servlet.ServletRequest; -import javax.servlet.ServletResponse; -import javax.ws.rs.WebApplicationException; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.extensions.HttpExtension; -import org.gcube.smartgears.extensions.resource.RemoteResource; -import org.gcube.smartgears.handlers.application.request.RequestError; -import org.junit.Test; - -import app.SomeApp; - -public class ExtensionsTest { - - String name = "name"; - String extension_path="/ext"; - - - @Test - public void areInstalledAndInitialised() { - - - final String response = "output"; - - @SuppressWarnings("serial") - ApplicationExtension extension = new HttpExtension(name,extension_path) { - - @Override - public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - assertNotNull(context()); //init has been invoked - res.getWriter().write(response); - } - - }; - - - - SomeApp app = new SomeApp(); - - app.extensions().set(extension); - - //we're only testing correct installation, not configuration now anything else - app.bypassExtensionsDeployment(); - - app.start(); - - String actual = app.send(request().at(Constants.root_mapping+extension_path)); - - assertEquals(response,actual); - } - - @SuppressWarnings("serial") - @XmlRootElement(name="unknown") - static class UnknownExtension extends HttpExtension { - - UnknownExtension() {} - - public UnknownExtension(String name, String mapping) { - super(name, mapping); - } - - @Override - public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - } - } - - @Test - public void failAppIfNotConfigured() { - - SomeApp app = new SomeApp(); - - app.bypassHandlerDeployment(); - - app.extensions().set(new UnknownExtension(name,extension_path)); - - ApplicationContext context= app.start(); - - assertEquals(failed,context.lifecycle().state()); - - } - - @Test - public void failAppIfConfiguredBadly() { - - SomeApp app = new SomeApp(); - - RemoteResource extension = new RemoteResource(); - extension.name(""); - extension.mapping(""); - - app.extensions().set(extension); - - app.bypassHandlerDeployment(); - - ApplicationContext context= app.start(); - - assertEquals(failed,context.lifecycle().state()); - - } - - - @Test - public void throwErrorsConvertedInHttpResponses() { - - - final RequestError error = invalid_request_error; - - @SuppressWarnings("serial") - ApplicationExtension extension = new HttpExtension(name,extension_path) { - - @Override - public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - error.fire(); - } - - }; - - SomeApp app = new SomeApp(); - - app.extensions().set(extension); - - //we're only testing correct installation, not configuration now anything else - app.bypassExtensionsDeployment(); - - app.start(); - - try { - app.send(request().at(Constants.root_mapping+extension_path)); - fail(); - } - catch(WebApplicationException e) { - - assertEquals(error.code(),e.getResponse().getStatus()); - } - - } - - @Test - public void areManagedLikeNativeServlets() { - - @SuppressWarnings("serial") - ApplicationExtension extension = new HttpExtension(name,extension_path) { - @Override - public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException { - } - }; - - SomeApp app = new SomeApp(); - - app.extensions().set(extension); - - app.bypassExtensionsDeployment(); - - //installs default filters - app.useDefaultHandlers(); - - app.start(); - - //call in no scope - try { - app.send(request().at(Constants.root_mapping+extension_path).inScope(null)); - fail(); - } - catch(WebApplicationException e) { - - assertEquals((String)e.getResponse().getEntity(),invalid_request_error.code(),e.getResponse().getStatus()); - } - } -} diff --git a/src/test/java/test/application/ProfileManagementTest.java b/src/test/java/test/application/ProfileManagementTest.java deleted file mode 100644 index 742c891..0000000 --- a/src/test/java/test/application/ProfileManagementTest.java +++ /dev/null @@ -1,74 +0,0 @@ -package test.application; - -import static junit.framework.Assert.*; -import static org.gcube.smartgears.Constants.*; - -import java.io.File; - -import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.common.resources.gcore.Resources; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; -import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; -import org.junit.BeforeClass; -import org.junit.Test; - -import app.SomeApp; - -public class ProfileManagementTest { - - public static ApplicationContext ctx; - - @BeforeClass - public static void startApp() { - - SomeApp app = new SomeApp(); - - app.handlers().set(new ProfileManager()); - - ctx = app.start(); - - } - - @Test - public void createsStoresAndPublishesAValidProfile() throws Exception { - - GCoreEndpoint profile = ctx.profile(); - - assertNotNull(profile); - - //assert profile has been created - File file = ctx.configuration().persistence().file(profile_file_path); - assertTrue(file.exists()); - - assertFalse(profile.scopes().isEmpty()); - - Resources.validate(profile); - - //assert status matches lifecycle's current state - ApplicationLifecycle lc = ctx.lifecycle(); - - assertEquals(profile.profile().deploymentData().status(),lc.state().remoteForm()); - - } - - @Test - public void loadsAndUpdatesProfile() throws Exception { - - SomeApp runtwice = new SomeApp(); - - runtwice.handlers().set(new ProfileManager()); - - runtwice.dirtyRun(); - - ApplicationContext ctx = runtwice.start(); - - - GCoreEndpoint profile = ctx.profile(); - - assertNotNull(profile); - - Resources.validate(profile); - } - -} diff --git a/src/test/java/test/application/RemoteResourceTest.java b/src/test/java/test/application/RemoteResourceTest.java deleted file mode 100644 index b8314b8..0000000 --- a/src/test/java/test/application/RemoteResourceTest.java +++ /dev/null @@ -1,129 +0,0 @@ -package test.application; - -import static app.Request.request; -import static org.gcube.smartgears.Constants.application_xml; -import static org.gcube.smartgears.Constants.content_type; -import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; -import static org.gcube.smartgears.extensions.HttpExtension.Method.POST; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - -import java.io.StringReader; - -import javax.xml.bind.JAXBContext; - -import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.common.resources.gcore.Resources; -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.extensions.resource.ConfigurationResource; -import org.gcube.smartgears.extensions.resource.FrontPageResource; -import org.gcube.smartgears.extensions.resource.LifecycleResource; -import org.gcube.smartgears.extensions.resource.LifecycleResource.State; -import org.gcube.smartgears.extensions.resource.ProfileResource; -import org.gcube.smartgears.lifecycle.application.ApplicationState; -import org.junit.BeforeClass; -import org.junit.Ignore; -import org.junit.Test; - -import app.Request; -import app.SomeApp; - -public class RemoteResourceTest { - - static final String path = "/resource"; - static JAXBContext jaxb; - static ApplicationContext context; - - static SomeApp app; - - @BeforeClass - public static void setup() throws Exception { - - jaxb = JAXBContext.newInstance(State.class); - - app = new SomeApp(); - - app.useDefaultHandlers(); - app.useDefaultExtensions(); - - context = app.start(); - } - - @Test - public void showsFrontpage() throws Exception { - - // unscoped request - Request request = request().at(resource(FrontPageResource.mapping)).inScope(null); - - app.send(request); - - //Thread.sleep(50000); enable to check interactively in browser - } - - @Test - public void showsConfiguration() throws Exception { - - //unscoped request - Request request = request().at(resource(ConfigurationResource.mapping)).inScope(null); - - app.send(request); - } - - @Test - public void showsProfile() throws Exception { - - //unscoped request - Request request = request().at(resource(ProfileResource.mapping)).inScope(null); - - String outcome = app.send(request); - - GCoreEndpoint profile = Resources.unmarshal(GCoreEndpoint.class, new StringReader(outcome)); - - assertEquals(context.profile().id(), profile.id()); - assertEquals(context.profile().profile().deploymentData().status(), profile.profile().deploymentData().status()); - } - - - - - - @Test - public void currentState() throws Exception { - - Request request = request().at(resource(LifecycleResource.mapping)).using(GET).inScope(null); - - String outcome = app.send(request); - - State state = (State) jaxb.createUnmarshaller().unmarshal(new StringReader(outcome)); - - assertEquals(context.lifecycle().state(),ApplicationState.valueOf(state.value)); - - } - - @Ignore - @Test - public void changeState() throws Exception { - - ApplicationState newstate = ApplicationState.stopped; - - assertFalse(context.lifecycle().state()==newstate); - - Request request = request().at(resource(LifecycleResource.mapping)).using(POST).inScope(null) - .with(content_type, application_xml).with("stopped"); - - app.httpSend(request); - - assertTrue(context.lifecycle().state()==newstate); - - request = request().at(resource(LifecycleResource.mapping)).using(POST).inScope(null) - .with(content_type, application_xml).with("active"); - - } - - // helper - private String resource(String resource) { - return Constants.root_mapping + path + resource; - } -} diff --git a/src/test/java/test/application/StartupTest.java b/src/test/java/test/application/StartupTest.java deleted file mode 100644 index a3f7cdb..0000000 --- a/src/test/java/test/application/StartupTest.java +++ /dev/null @@ -1,231 +0,0 @@ -package test.application; - -import static app.Request.request; -import static org.gcube.smartgears.Constants.profile_file_path; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.active; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.File; - -import org.gcube.common.resources.gcore.Resource; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.informationsystem.publisher.exception.RegistryNotFoundException; -import org.gcube.smartgears.Constants; -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.application.ApplicationEvent; -import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent.Start; -import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; -import org.gcube.smartgears.handlers.application.RequestHandler; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.junit.After; -import org.junit.Test; -import org.mockito.Matchers; -import org.mockito.Mockito; - -import app.SomeApp; -import utils.TestUtils.Box; - -public class StartupTest { - - SomeApp app = new SomeApp(); - - @After - public void teardown() { - app.stop(); - } - - @Test - public void succeedsWithDefaults() throws Exception { - - - app.useDefaultHandlers(); - app.useDefaultExtensions(); - - ApplicationContext ctx = app.start(); - - assertEquals(active,ctx.lifecycle().state()); - - //profile is shared in servlet context - assertEquals(ctx,ctx.application().getAttribute(Constants.context_attribute)); - - } - - @Test - public void stillStoresProfileWhenPublicationFails() throws Exception { - - app.useDefaultHandlers(); - - ScopedPublisher failingPublisher = Mockito.mock(ScopedPublisher.class); - when(failingPublisher.create(any(Resource.class), Matchers.anyListOf(String.class))).thenThrow(new RegistryNotFoundException()); - - app.usePublisher(failingPublisher); - - ApplicationContext ctx = app.start(); - - Thread.sleep(100); //a little bit of time for failure to propagate - - //application has failed - assertEquals(failed,ctx.lifecycle().state()); - - //profile has been created - File file = ctx.configuration().persistence().file(profile_file_path); - assertTrue(file.exists()); - - } - - @Test - @SuppressWarnings("all") - public void invokesLifecycleHandlers() { - - ApplicationLifecycleHandler witness = mock(ApplicationLifecycleHandler.class); - - app.handlers().set(witness); - - //as we're using mocks, let us bypass JAXB configuration mechanisms - app.bypassHandlerDeployment(); - - app.start(); - - verify(witness).onEvent(any(ApplicationEvent.class)); - } - - @Test - @SuppressWarnings("all") - public void registersRequestsHandlers() { - - Box handlerIsInvoked = new Box(); - - RequestHandler witness = mock(RequestHandler.class); - - app.handlers().set(witness); - - app.bypassHandlerDeployment(); - - app.start(); - - app.send(request()); - - //invoked for request and response - verify(witness,times(2)).onEvent(isA(ApplicationEvent.class)); - } - - //@Ignore //inexplicable sometimes fails as configuration is not removed - @Test - public void failsIfConfigurationIsInvalid() { - - app.configuration().name(null).serviceClass(null).description(null).version(null).persistence(null); - - ApplicationContext ctx = app.start(); - - assertEquals(failed,ctx.lifecycle().state()); - } - - @Test - public void failsIfHandlerFails() throws Throwable { - - ApplicationLifecycleHandler failingHandler = mock(ApplicationLifecycleHandler.class); - doThrow(new RuntimeException("simulated handler failure")).when(failingHandler).onEvent(isA(Start.class)); - - app.handlers().set(failingHandler); - - app.bypassHandlerDeployment(); - - ApplicationContext ctx = app.start(); - - assertEquals(failed,ctx.lifecycle().state()); - - } - - @Test - public void canUseExternalConfiguration() { - - app.asExternal(); - - app.start(); - - assertTrue(app.isActive()); - } - - - @Test - public void canUseMergedConfiguration() { - - ApplicationConfiguration config = new DefaultApplicationConfiguration(); - config.persistence(new LocalPersistence(new File(".").getAbsolutePath())); - - ApplicationContext context = app.start(); - - assertTrue(app.isActive()); - - app.withExternal(config); - - assertEquals(config.persistence(),context.configuration().persistence()); - - } - - - @Test - public void failsIfAllStartScopesAreInvalid() throws Exception { - - ApplicationConfiguration config = new DefaultApplicationConfiguration(); - - //config.startScopes("bad/scope","even/badder"); - - app.useDefaultHandlers(); - - ApplicationContext context = app.start(); - - app.withExternal(config); - - assertEquals(failed,context.lifecycle().state()); - - - - } - - @Test - public void canStartInVreScope() throws Exception { - - ApplicationConfiguration config = new DefaultApplicationConfiguration(); - - //tring vre = "/"+app.containerConfiguration().infrastructure()+"/"+app.containerConfiguration().startVOs().get(0)+"/vre"; - - //config.startScopes(vre,"/bad/scope"); - - app.useDefaultHandlers(); - - ApplicationContext context = app.start(); - - app.withExternal(config); - - assertEquals(active,context.lifecycle().state()); - - //Set runningScopes = new HashSet<>(context.profile(GCoreEndpoint.class).scopes().asCollection()); - - //assertEquals(singleton(vre),runningScopes); - - - - - } - - - @Test(expected=RuntimeException.class) - public void failsIfConfigurationIsMissing() { - - app.bypassConfigurationDeployment(); - - app.start(); - } -} diff --git a/src/test/java/test/container/ConfigurationTest.java b/src/test/java/test/container/ConfigurationTest.java deleted file mode 100644 index 24936fc..0000000 --- a/src/test/java/test/container/ConfigurationTest.java +++ /dev/null @@ -1,40 +0,0 @@ -package test.container; - -import java.io.StringWriter; - -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.ini4j.Ini; -import org.ini4j.Profile.Section; -import org.junit.Test; - -public class ConfigurationTest { - - @Test - public void containerConfigurationBinds() throws Exception { - - ContainerConfiguration bound = ContainerConfiguration - .load(ConfigurationTest.class.getResourceAsStream("/test-configuration.ini")); - - bound.validate(); - - } - - @Test - public void iniStore() throws Exception { - Ini ini = new Ini(); - - // lets add a section, it will create needed intermediate sections as well - ini.add("root/child/sub"); - - Section rsec = ini.get("root"); - rsec.add("test", "team"); - Section csec = rsec.getChild("child"); - csec.add("testchild", "pappo"); - Section ssec = csec.getChild("sub"); - ssec.add("testSec", "pippo"); - - StringWriter sw = new StringWriter(); - ini.store(sw); - - } -} diff --git a/src/test/java/test/container/ContainerLifecycleTest.java b/src/test/java/test/container/ContainerLifecycleTest.java deleted file mode 100644 index 87f387b..0000000 --- a/src/test/java/test/container/ContainerLifecycleTest.java +++ /dev/null @@ -1,79 +0,0 @@ -package test.container; - -import static org.junit.Assert.*; - -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.lifecycle.application.ApplicationState; -import org.gcube.smartgears.lifecycle.container.ContainerState; -import org.gcube.smartgears.managers.ContainerManager; -import org.junit.After; -import org.junit.Before; -import org.junit.Ignore; -import org.junit.Test; - -import app.SomeApp; - -public class ContainerLifecycleTest { - - - SomeApp app; - - - @Before - public void init() { - app = new SomeApp(); - } - - @After - public void teardown() { - app.stop(); - } - - @Test - public void containerGoesToPartActiveWhenAppFails() { - - - ApplicationContext actx = app.start(); - - ContainerContext ctx = actx.container(); - - assertEquals(ContainerState.active,ctx.lifecycle().state()); - - actx.lifecycle().moveTo(ApplicationState.failed); - - assertEquals(ContainerState.partActive,ctx.lifecycle().state()); - } - - @Test - public void containerGoesToPartActiveWhenAppStops() { - - ApplicationContext actx = app.start(); - - ContainerContext ctx = actx.container(); - - assertEquals(ContainerState.active,ctx.lifecycle().state()); - - actx.lifecycle().moveTo(ApplicationState.stopped); - - assertEquals(ContainerState.partActive,ctx.lifecycle().state()); - } - - - //used interactively to study shutdown - @Ignore - @Test - public void containerShutsdown() throws Exception { - - ApplicationContext actx = app.start(); - - ContainerContext ctx = actx.container(); - - assertEquals(ContainerState.active,ctx.lifecycle().state()); - - ContainerManager.instance.stop(true); - app.stop(); - - Thread.sleep(10000); - } -} diff --git a/src/test/java/test/container/ProfileManagementTest.java b/src/test/java/test/container/ProfileManagementTest.java deleted file mode 100644 index ffcdc22..0000000 --- a/src/test/java/test/container/ProfileManagementTest.java +++ /dev/null @@ -1,98 +0,0 @@ -package test.container; - -import static junit.framework.Assert.*; -import static org.gcube.smartgears.Constants.*; -import static org.gcube.smartgears.lifecycle.container.ContainerState.*; - -import java.io.File; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; - -import org.gcube.common.events.Observes; -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.common.resources.gcore.Resources; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.context.container.ContainerContext; -import org.junit.Test; - -import app.SomeApp; - -public class ProfileManagementTest { - - @Test - public void createsStoresAndPublishesAValidProfile() throws Exception { - - ContainerContext ctx = startAppAndGetContainerContext(); - - HostingNode node = ctx.profile(); - - assertNotNull(node); - - //assert profile has been created - File profile = ctx.configuration().persistence().file(container_profile_file_path); - assertTrue(profile.exists()); - - assertFalse(node.scopes().isEmpty()); - - Resources.validate(node); - - } - - @Test - public void loadsAndUpdatesProfile() throws Exception { - - startAppAndGetContainerContext(); - - SomeApp runtwice = new SomeApp(); - - runtwice.dirtyRun(); - - ContainerContext ctx = runtwice.start().container(); - - assertNotNull(ctx.profile()); - - HostingNode node = ctx.profile(); - - Resources.validate(node); - } - - - @Test - public void periodicallyUpdatesAndPublishesProfile() throws Exception { - - SomeApp app = new SomeApp(); - - //app.containerConfiguration().publicationFrequency(1); - - ContainerContext ctx = app.start().container(); - - final CountDownLatch latch = new CountDownLatch(1); - - assertEquals(active,ctx.lifecycle().state()); - - ctx.events().subscribe(new Object() { - - @Observes - void profileHasChangedAfterPeriodicUpdate(HostingNode ignore) { - latch.countDown(); - } - - }); - - if (!latch.await(4,TimeUnit.SECONDS)) - fail(); - - ctx.lifecycle().moveTo(stopped); //should stop periodic updates - - } - - - ContainerContext startAppAndGetContainerContext() { - - SomeApp app = new SomeApp(); - - ApplicationContext appCtx = app.start(); - - return appCtx.container(); - } -} diff --git a/src/test/java/test/container/StartupTest.java b/src/test/java/test/container/StartupTest.java deleted file mode 100644 index db0d4d9..0000000 --- a/src/test/java/test/container/StartupTest.java +++ /dev/null @@ -1,65 +0,0 @@ -package test.container; - -import static org.gcube.smartgears.Constants.*; -import static org.gcube.smartgears.lifecycle.container.ContainerState.*; -import static org.junit.Assert.*; - -import org.gcube.smartgears.context.application.ApplicationContext; -import org.junit.After; -import org.junit.Test; - -import app.SomeApp; - -public class StartupTest { - - SomeApp app = new SomeApp(); - - @After - public void teardown() { - app.stop(); - } - - @Test(expected=RuntimeException.class) - public void failsIfHomeIsNotConfigured() { - - System.clearProperty(ghn_home_property); - - app.start(); - - assertFalse(app.isActive()); - } - - @Test(expected=RuntimeException.class) - public void failsIfInstallationFolderIsInvalid() { - - System.setProperty(ghn_home_property,"foo"); - - app.start(); - - assertFalse(app.isActive()); - - } - - @Test(expected=RuntimeException.class) - public void failsIfConfigurationIsInvalid() { - - //app.containerConfiguration().hostname(null); - - app.start(); - - assertFalse(app.isActive()); - - } - - @Test - public void leavesContainerToActive() { - - ApplicationContext ctx = app.start(); - - assertEquals(active,ctx.container().lifecycle().state()); - - assertTrue(app.isActive()); - } - - -} diff --git a/src/test/resources/container.ini b/src/test/resources/container.ini new file mode 100644 index 0000000..e1a8526 --- /dev/null +++ b/src/test/resources/container.ini @@ -0,0 +1,41 @@ +[node] +; mandatory +; optional fields: mode (=online), publication-frequency-seconds (=60), authorizeChildrenContext (=false) +mode = online +hostname = dlib29.isti.cnr.it +protocol= http +port = 8080 +infrastructure = gcube +authorizeChildrenContext = true +publicationFrequencyInSeconds = 60 + +[properties] +; not mandatory +SmartGearsDistribution = 0.0.1 +SmartGearsDistributionBundle = UnBundled + +[site] +; mandatory +; optional fields: latitude, logitude +country = it +location = rome + +;[proxy] +; not mandatory +;protocol = https +;hostname = proxy +;port = 80 + +[authorization] +; mandatory +; optional fields: provider factory (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) +factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory +credentials.class = org.gcube.smartgears.security.SimpleCredentials +credentials.clientID = testClient +credentials.secret = testSecret +credentials.endpoint = testSecret + +;[persistence] +; not mandatory (default is LocalPersistence writing in the ghn home) +;class = utils.PersistenceWriterTest +;location = /tmp diff --git a/src/test/resources/test-configuration.ini b/src/test/resources/test-configuration.ini index 28e53ff..683fb11 100644 --- a/src/test/resources/test-configuration.ini +++ b/src/test/resources/test-configuration.ini @@ -28,11 +28,12 @@ port = 80 [authorization] ; mandatory -; optional fields: provider (=org.gcube.smartgears.security.DefaultAuthorizationProvider) -provider = org.gcube.smartgears.security.DefaultAuthorizationProvider +; optional fields: factory provider (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) +factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.clientID = testClient credentials.secret = testSecret +credentials.enpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token [persistence] ; not mandatory (default is LocalPersistence writing in the ghn home) From 230ae3bde92af7e5e587fdac30fe334d0583c63a Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Thu, 26 May 2022 14:39:31 +0200 Subject: [PATCH 16/49] auth provider modified --- .../ContainerConfigurationBinder.java | 3 +- .../application/lifecycle/ProfileManager.java | 4 +- .../lifecycle/ContainerPublisher.java | 3 +- .../smartgears/managers/ContainerManager.java | 2 +- .../security/AuthorizationProvider.java | 2 +- .../AuthorizationProviderFactory.java | 3 +- .../security/SimpleCredentials.java | 11 ----- .../DefaultAuthorizationProvider.java | 14 +++++-- .../DefaultAuthorizationProviderFactory.java | 4 +- src/test/resources/container.ini | 2 +- src/test/resources/test-configuration.ini | 41 ------------------- 11 files changed, 22 insertions(+), 67 deletions(-) delete mode 100644 src/test/resources/test-configuration.ini diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index b7b5325..01919b9 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -114,6 +114,7 @@ public class ContainerConfigurationBinder { if (authorizationSection != null) { String provider = authorizationSection.get("factory"); + String authEndpoint = authorizationSection.get("endpoint"); AuthorizationProviderFactory authProviderFactory; if (provider!=null) { try { @@ -138,7 +139,7 @@ public class ContainerConfigurationBinder { } authorizationSection.to(credentials, "credentials."); - AuthorizationProvider authProvider = authProviderFactory.connect(credentials); + AuthorizationProvider authProvider = authProviderFactory.connect(credentials, authEndpoint); conf.setAuthorizationProvider(authProvider); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java index 8aa9daa..2418054 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java @@ -164,7 +164,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { @Observes(value = addToContext) void addTo(String token) { try { - log.trace("publishing application with new token"); + log.trace("publishing application in new context"); publisher.addTo(Collections.singleton(token)); publisher.update(); }catch (Exception e) { @@ -183,7 +183,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { @Observes(value = removeFromContext) void removeFrom(String token) { try { - log.trace("unpublishing application with token"); + log.trace("unpublishing application from context"); publisher.removeFrom(Collections.singleton(token)); publisher.update(); }catch (Exception e) { diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java index bbf7110..a883ba7 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java @@ -47,8 +47,7 @@ public class ContainerPublisher extends AbstractProfilePublisher { @Override protected Set getAllowedContexts() { - // TODO Auto-generated method stub - return null; + return context.configuration().allowedContexts(); } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index f44ad3d..c2c2d54 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -101,7 +101,7 @@ public class ContainerManager { Set foundContexts; try { - foundContexts = context.configuration().authorizationProvider().getAllowedContexts(); + foundContexts = context.configuration().authorizationProvider().getContexts(); } catch (Exception e) { log.error("error authorizing container",e); throw new RuntimeException("error authorizing container, moving the container to failed",e); diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index abafa2d..08cb7b4 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -4,5 +4,5 @@ import java.util.Set; public interface AuthorizationProvider { - Set getAllowedContexts(); + Set getContexts(); } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java index c18bcd7..6892b20 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java @@ -2,6 +2,7 @@ package org.gcube.smartgears.security; public interface AuthorizationProviderFactory { - T connect(Credentials credentials); + T connect(Credentials credentials, String endpoint); + } diff --git a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java index ac45581..b9aca8b 100644 --- a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java +++ b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java @@ -11,9 +11,6 @@ public class SimpleCredentials implements Credentials{ @NotNull @NotEmpty String secret; - @NotNull @NotEmpty - String endpoint; - public String getClientID() { return clientID; } @@ -21,14 +18,6 @@ public class SimpleCredentials implements Credentials{ public void setClientID(String clientID) { this.clientID = clientID; } - - public String getEndpoint() { - return endpoint; - } - - public void setEndpoint(String endpoint) { - this.endpoint = endpoint; - } public String getSecret() { return secret; diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index 686426e..d030836 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -25,16 +25,22 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { private SimpleCredentials credentials; - public DefaultAuthorizationProvider(SimpleCredentials credentials) { + private String endpoint; + + public DefaultAuthorizationProvider(SimpleCredentials credentials, String endpoint) { this.credentials = credentials; + this.endpoint = endpoint; } - @Override - public Set getAllowedContexts() { + public Set getContexts() { Set contexts = new HashSet(); try { - TokenResponse response = client.queryOIDCToken(new URL(credentials.getEndpoint()), credentials.getClientID(), credentials.getSecret()); + TokenResponse response; + if (this.endpoint == null) + response = client.queryOIDCToken(credentials.getClientID(), credentials.getSecret()); + else + response = client.queryOIDCToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret()); Map resourceAccess = ModelUtils.getAccessTokenFrom(response).getResourceAccess(); for (String context : resourceAccess.keySet()) { try { diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java index 9903c0d..9fac9e0 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java @@ -7,10 +7,10 @@ import org.gcube.smartgears.security.SimpleCredentials; public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory{ @Override - public DefaultAuthorizationProvider connect(Credentials credentials) { + public DefaultAuthorizationProvider connect(Credentials credentials, String enpoint) { if (!SimpleCredentials.class.isInstance(credentials)) throw new IllegalArgumentException("invalid credential type passed"); - return new DefaultAuthorizationProvider((SimpleCredentials)credentials); + return new DefaultAuthorizationProvider((SimpleCredentials)credentials, enpoint); } diff --git a/src/test/resources/container.ini b/src/test/resources/container.ini index e1a8526..dd6a102 100644 --- a/src/test/resources/container.ini +++ b/src/test/resources/container.ini @@ -30,10 +30,10 @@ location = rome ; mandatory ; optional fields: provider factory (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory +endpoint = testEndpoint credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.clientID = testClient credentials.secret = testSecret -credentials.endpoint = testSecret ;[persistence] ; not mandatory (default is LocalPersistence writing in the ghn home) diff --git a/src/test/resources/test-configuration.ini b/src/test/resources/test-configuration.ini deleted file mode 100644 index 683fb11..0000000 --- a/src/test/resources/test-configuration.ini +++ /dev/null @@ -1,41 +0,0 @@ -[node] -; mandatory -; optional fields: mode (=online), publication-frequency-seconds (=60), authorizeChildrenContext (=false) -mode = offline -hostname = localhost -protocol= https -port = 8080 -infrastructure = gcube -authorizeChildrenContext = true -publicationFrequencyInSeconds = 60 - -[properties] -; not mandatory -SmartGearsDistribution = 0.0.1 -SmartGearsDistributionBundle = UnBundled - -[site] -; mandatory -; optional fields: latitude, logitude -country = it -location = rome - -[proxy] -; not mandatory -protocol = https -hostname = proxy -port = 80 - -[authorization] -; mandatory -; optional fields: factory provider (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) -factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory -credentials.class = org.gcube.smartgears.security.SimpleCredentials -credentials.clientID = testClient -credentials.secret = testSecret -credentials.enpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token - -[persistence] -; not mandatory (default is LocalPersistence writing in the ghn home) -class = utils.PersistenceWriterTest -location = /tmp From 64bef37271d2071c372c0e51616518875be1d097 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 30 May 2022 18:29:46 +0200 Subject: [PATCH 17/49] Removed old VAleve --- .../lifecycle/ServicePublisher.java | 3 +- .../request/RequestAccounting.java | 59 +++++++------ .../application/request/RequestValidator.java | 12 ++- .../container/lifecycle/ProfileBuilder.java | 2 + .../security/AuthorizationProvider.java | 4 + .../DefaultAuthorizationProvider.java | 22 +++++ .../utils/GcubeAccountingValve.java | 85 ------------------- 7 files changed, 65 insertions(+), 122 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java index 538834b..1aad5e3 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java @@ -54,8 +54,7 @@ public class ServicePublisher extends AbstractProfilePublisher { @Override protected Set getAllowedContexts() { - // TODO Auto-generated method stub - return null; + return context.container().configuration().authorizationProvider().getContexts(); } } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 74f6f03..3fad47f 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -8,8 +8,7 @@ import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; -import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.context.application.ApplicationContext; @@ -21,8 +20,6 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Timer; -import io.micrometer.core.instrument.Timer.Sample; @XmlRootElement(name = Constants.request_accounting) public class RequestAccounting extends RequestHandler { @@ -40,8 +37,11 @@ public class RequestAccounting extends RequestHandler { @Override public void handleRequest(RequestEvent e) { - ApplicationContext context = e.context(); + ApplicationContext appContext = e.context(); + + String context = getContext(appContext); + String calledMethod = e.request().getHeader(Constants.called_method_header); if (calledMethod==null){ calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); @@ -54,22 +54,18 @@ public class RequestAccounting extends RequestHandler { startCallThreadLocal.set(System.currentTimeMillis()); log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", - context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, e.request().getRemoteHost(), ScopeProvider.instance.get()); + appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), + caller, e.request().getRemoteHost(), context ); } @Override public void handleResponse(ResponseEvent e) { - ApplicationContext context = e.context(); + ApplicationContext appContext = e.context(); try { - boolean resetScope = false; - if (ScopeProvider.instance.get()==null && SecurityTokenProvider.instance.get()==null){ - String infrastructure = e.context().container().configuration().infrastructure(); - ScopeProvider.instance.set("/"+infrastructure); - resetScope = true; - } + + String context = getContext(appContext); String caller = "Unknown"; String callerQualifier = "UNKNOWN"; @@ -80,23 +76,22 @@ public class RequestAccounting extends RequestHandler { boolean success = e.response().getStatus()<400; - if (context.container().configuration().mode()!=Mode.offline) - generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context); + if (appContext.container().configuration().mode()!=Mode.offline) + generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context, appContext); long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); Metrics.globalRegistry.timer("http.requests", "response",Integer.toString(e.response().getStatus()) - , "context", ScopeProvider.instance.get(), "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, - "caller-username", caller, "service-class", context.configuration().serviceClass(), "service-name", context.configuration().name(), + , "context", context, "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, + "caller-username", caller, "service-class", appContext.configuration().serviceClass(), "service-name", appContext.configuration().name(), "method", InnerMethodName.instance.get()).record(durationInMillis, TimeUnit.MILLISECONDS); log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", - context.configuration().name(),context.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, callerIp, ScopeProvider.instance.get(), success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); + appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), + caller, callerIp, context, success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); startCallThreadLocal.remove(); InnerMethodName.instance.reset(); - if (resetScope) - ScopeProvider.instance.reset(); + }catch (Exception e1) { log.error("error on accounting",e); throw e1; @@ -104,19 +99,19 @@ public class RequestAccounting extends RequestHandler { } - void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, ApplicationContext context){ - AccountingPersistenceFactory.setFallbackLocation(context.container().configuration().accountingFallbackLocation()); + void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, String gcubeContext, ApplicationContext appContext){ + AccountingPersistenceFactory.setFallbackLocation(appContext.container().configuration().accountingFallbackLocation()); AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); try{ serviceUsageRecord.setConsumerId(caller); serviceUsageRecord.setCallerQualifier(callerQualifier); - serviceUsageRecord.setScope(ScopeProvider.instance.get()); - serviceUsageRecord.setServiceClass(context.configuration().serviceClass()); - serviceUsageRecord.setServiceName(context.configuration().name()); + serviceUsageRecord.setScope(gcubeContext); + serviceUsageRecord.setServiceClass(appContext.configuration().serviceClass()); + serviceUsageRecord.setServiceName(appContext.configuration().name()); - serviceUsageRecord.setHost(context.container().configuration().hostname()+":"+context.container().configuration().port()); + serviceUsageRecord.setHost(appContext.container().configuration().hostname()+":"+appContext.container().configuration().port()); serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get()); serviceUsageRecord.setCallerHost(remoteHost); serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); @@ -128,6 +123,14 @@ public class RequestAccounting extends RequestHandler { } } + private String getContext(ApplicationContext appContext) { + String infrastructure = appContext.container().configuration().infrastructure(); + String context= "/"+infrastructure; + if (SecretManagerProvider.instance.get() != null) + context = SecretManagerProvider.instance.get().getContext(); + return context; + } + @Override public String toString() { return getName(); diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index c8a39b3..3766cdd 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -6,14 +6,12 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.app import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.crypto.dsig.keyinfo.RetrievalMethod; -import org.gcube.common.scope.api.ScopeProvider; import org.gcube.common.scope.impl.ScopeBean; import org.gcube.common.scope.impl.ScopeBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; +import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.GCubeSecret; -import org.gcube.common.security.secrets.JWTSecret; import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; @@ -54,7 +52,7 @@ public class RequestValidator extends RequestHandler { if (appContext.container().configuration().mode()!=Mode.offline) { validateScopeCall(); - validatePolicy(ScopeProvider.instance.get(), call); + validatePolicy(call); } } @@ -106,7 +104,7 @@ public class RequestValidator extends RequestHandler { Secret secret = SecretManagerProvider.instance.get(); - if (secret!= null){ + if (secret == null){ log.warn("rejecting call to {}, authorization required",appContext.name()); RequestError.request_not_authorized_error.fire(appContext.name()+": authorization required"); } @@ -117,7 +115,7 @@ public class RequestValidator extends RequestHandler { return getName(); } - private void validatePolicy(String scope, RequestEvent call){ + private void validatePolicy(RequestEvent call){ //TODO: must be re-think } @@ -135,7 +133,7 @@ public class RequestValidator extends RequestHandler { Secret secret = null; if (accessToken!=null) - secret = new JWTSecret(accessToken); + secret = new AccessTokenSecret(accessToken); else if (token!=null) secret = new GCubeSecret(token); return secret; diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java index 4315a6b..701ff8d 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java @@ -71,6 +71,8 @@ public class ProfileBuilder { node.profile().description().newArchitecture().platformType(System.getProperty("os.arch")).smpSize(0) .smtSize(0); + node.profile().newSite().domain("It").country("It").location("Rome").latitude("1").longitude("1"); + ArrayList> info = cpuInfo(); Group processors = node.profile().description().processors(); diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index 08cb7b4..2393a5f 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -2,7 +2,11 @@ package org.gcube.smartgears.security; import java.util.Set; +import org.gcube.common.security.secrets.Secret; + public interface AuthorizationProvider { Set getContexts(); + + Secret getSecretForContext(String context); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index d030836..ef8e935 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -12,6 +12,8 @@ import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.security.secrets.AccessTokenSecret; +import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; @@ -46,6 +48,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { try { ScopeBean scope = new ScopeBean(context.replaceAll("%2F", "/")); contexts.add(scope.toString()); + LOG.info("found context {}",context); }catch (IllegalArgumentException e) { LOG.warn("invalid context found in token: {}", context); } @@ -57,4 +60,23 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { return contexts; } + + @Override + public Secret getSecretForContext(String context) { + try { + TokenResponse response; + if (this.endpoint == null) + response = client.queryUMAToken(credentials.getClientID(), credentials.getSecret(), context, null); + else + response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); + + return new AccessTokenSecret(response.getAccessToken()); + + } catch (Exception e) { + LOG.error("error getting OIDToken from keycloak",e); + throw new RuntimeException("error getting access token for context "+context, e); + } + + } + } diff --git a/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java b/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java deleted file mode 100644 index 632b74d..0000000 --- a/src/main/java/org/gcube/smartgears/utils/GcubeAccountingValve.java +++ /dev/null @@ -1,85 +0,0 @@ -package org.gcube.smartgears.utils; - -import java.io.IOException; - -import javax.servlet.ServletException; - -import org.apache.catalina.connector.Request; -import org.apache.catalina.connector.Response; -import org.apache.catalina.valves.ValveBase; -import org.gcube.accounting.datamodel.UsageRecord.OperationResult; -import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; -import org.gcube.accounting.persistence.AccountingPersistence; -import org.gcube.accounting.persistence.AccountingPersistenceFactory; -import org.gcube.common.scope.api.ScopeProvider; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class GcubeAccountingValve extends ValveBase { - - private static Logger log = LoggerFactory.getLogger(GcubeAccountingValve.class); - - private String infra; - private String serviceClass; - private String serviceName; - private String hostAndPort; - - public void setInfra(String infra) { - this.infra = infra; - } - - public void setServiceClass(String serviceClass) { - this.serviceClass = serviceClass; - } - - public void setServiceName(String serviceName) { - this.serviceName = serviceName; - } - - public void setHostAndPort(String hostAndPort) { - this.hostAndPort = hostAndPort; - } - - @Override - public void invoke(Request request, Response response) throws IOException, ServletException { - try { - String callerIp = request.getHeader("x-forwarded-for"); - if (callerIp == null) { - callerIp = request.getRemoteAddr(); - } - - boolean success = response.getStatus()<400; - ScopeProvider.instance.set(infra); - AccountingPersistenceFactory.setFallbackLocation("/tmp"); - AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); - ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); - try{ - - serviceUsageRecord.setConsumerId("UNKNOWN"); - serviceUsageRecord.setCallerQualifier("UNKNOWN"); - serviceUsageRecord.setScope(infra); - serviceUsageRecord.setServiceClass(serviceClass); - serviceUsageRecord.setServiceName(serviceName); - serviceUsageRecord.setDuration(200l); - serviceUsageRecord.setHost(hostAndPort); - serviceUsageRecord.setCalledMethod(request.getRequestURI()); - serviceUsageRecord.setCallerHost(callerIp); - serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); - persistence.account(serviceUsageRecord); - log.info("Request: {} {} {} {} ", infra, request.getContextPath(), request.getRequestURI(), success); - }catch(Exception ex){ - log.warn("invalid record passed to accounting ",ex); - }finally { - ScopeProvider.instance.reset(); - } - - }catch (Exception e) { - log.error("error executing valve", e); - } - getNext().invoke(request, response); - } - - - - -} From 4b619414a70d42305798fbab6d9367c7047f2ce0 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 30 May 2022 18:55:35 +0200 Subject: [PATCH 18/49] removed old providers --- .../handlers/AbstractProfilePublisher.java | 28 ++----------------- .../smartgears/utils/InnerMethodName.java | 3 +- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java b/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java index eaa3752..9bf4931 100644 --- a/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java +++ b/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java @@ -7,9 +7,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Set; -import org.gcube.common.authorization.library.provider.SecurityTokenProvider; import org.gcube.common.resources.gcore.Resource; -import org.gcube.common.scope.api.ScopeProvider; import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.provider.ProviderFactory; import org.slf4j.Logger; @@ -44,11 +42,7 @@ public abstract class AbstractProfilePublisher

implements Pr log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset(); if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); profile = publisher.remove(profile, new ArrayList(contexts)); @@ -56,8 +50,6 @@ public abstract class AbstractProfilePublisher

implements Pr } catch (Exception e) { rethrowUnchecked(e); } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); if (isRoot()) Thread.currentThread().setContextClassLoader(contextCL); } @@ -69,7 +61,7 @@ public abstract class AbstractProfilePublisher

implements Pr public void addToAll(){ this.addTo(getAllowedContexts()); } - + /** * Adds for the first time the current resource profile of the application in one or more scopes. * @param contexts the contexts @@ -83,20 +75,12 @@ public abstract class AbstractProfilePublisher

implements Pr log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset();; - if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); - ScopeProvider.instance.set(contexts.stream().findFirst().get()); - profile = publisher.create(profile, new ArrayList(contexts)); - + if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); + profile = publisher.create(profile, new ArrayList(contexts)); } catch (Exception e) { rethrowUnchecked(e); } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); if (isRoot()) Thread.currentThread().setContextClassLoader(contextCL); } @@ -112,11 +96,7 @@ public abstract class AbstractProfilePublisher

implements Pr log.debug("using context {}",contextCL.getClass().getSimpleName()); - String previousToken = SecurityTokenProvider.instance.get(); - String previousScope = ScopeProvider.instance.get(); try{//This classloader set is needed for the jaxb context - if (previousToken!=null) - SecurityTokenProvider.instance.reset(); if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); @@ -125,8 +105,6 @@ public abstract class AbstractProfilePublisher

implements Pr } catch (Exception e) { rethrowUnchecked(e); } finally{ - SecurityTokenProvider.instance.set(previousToken); - ScopeProvider.instance.set(previousScope); if (isRoot()) Thread.currentThread().setContextClassLoader(contextCL); } diff --git a/src/main/java/org/gcube/smartgears/utils/InnerMethodName.java b/src/main/java/org/gcube/smartgears/utils/InnerMethodName.java index 9c81c21..692975d 100644 --- a/src/main/java/org/gcube/smartgears/utils/InnerMethodName.java +++ b/src/main/java/org/gcube/smartgears/utils/InnerMethodName.java @@ -1,6 +1,5 @@ package org.gcube.smartgears.utils; -import org.gcube.common.authorization.library.provider.CalledMethodProvider; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -8,7 +7,7 @@ public class InnerMethodName { public static InnerMethodName instance = new InnerMethodName(); - private static Logger logger = LoggerFactory.getLogger(CalledMethodProvider.class); + private static Logger logger = LoggerFactory.getLogger(InnerMethodName.class); // Thread local variable containing each thread's ID private static final InheritableThreadLocal threadMethod = From 961676484f3c795a62d5725fd3778e24cecc2385 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 8 Jun 2022 17:42:32 +0200 Subject: [PATCH 19/49] removing gcore resource dependencies from smartgears --- pom.xml | 24 +++---- .../application/ApplicationContext.java | 4 -- .../DefaultApplicationContext.java | 8 --- .../resource/FrontPageResource.java | 8 +-- .../extensions/resource/MetricsResource.java | 6 -- .../extensions/resource/ProfileResource.java | 4 +- .../application/lifecycle/ProfileBuilder.java | 71 ------------------- .../application/lifecycle/ProfileManager.java | 2 - .../lifecycle/ServicePublisher.java | 61 ---------------- .../application/request/RequestValidator.java | 6 +- .../smartgears/publishing/Publisher.java | 15 ++++ 11 files changed, 32 insertions(+), 177 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java create mode 100644 src/main/java/org/gcube/smartgears/publishing/Publisher.java diff --git a/pom.xml b/pom.xml index b17f221..cca1843 100644 --- a/pom.xml +++ b/pom.xml @@ -60,7 +60,7 @@ org.gcube.common common-security - + org.gcube.data.publishing document-store-lib @@ -76,16 +76,6 @@ slf4j-api - - org.gcube.resources - registry-publisher - - - - org.gcube.resources - common-gcore-resources - - org.ini4j ini4j @@ -100,13 +90,17 @@ org.gcube.core - common-scope + common-events + [1.0.0,2.0.0-SNAPSHOT) - org.gcube.core - common-events - [1.0.0,2.0.0-SNAPSHOT) + org.gcube.common.security + gcube-secrets + + + javax.ws.rs + javax.ws.rs-api diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java index a7a8f06..d213e29 100644 --- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java @@ -3,7 +3,6 @@ package org.gcube.smartgears.context.application; import javax.servlet.ServletContext; import org.gcube.common.events.Hub; -import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; @@ -34,9 +33,6 @@ public interface ApplicationContext { * @return the configuration */ ApplicationConfiguration configuration(); - - - GCoreEndpoint profile(); /** * Returns the lifecycle of the application. diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 9536401..2592ca9 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -1,11 +1,8 @@ package org.gcube.smartgears.context.application; -import static org.gcube.smartgears.Constants.profile_property; - import javax.servlet.ServletContext; import org.gcube.common.events.Hub; -import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; @@ -65,11 +62,6 @@ public class DefaultApplicationContext implements ApplicationContext { return container; } - @Override - public GCoreEndpoint profile() { - return properties().lookup(profile_property).value(GCoreEndpoint.class); - } - @Override public String name() { //little shortcut for ease of logging return configuration.name(); diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index d3e175a..2e3101c 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -11,7 +11,6 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -23,7 +22,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.security.ContextBean; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; import org.slf4j.Logger; @@ -94,12 +93,11 @@ public class FrontPageResource extends ApiResource { String infrastructure = context().container().configuration().infrastructure(); StringBuilder voValue = new StringBuilder(); - Collection scopes = context().profile().scopes().asCollection(); Set vos = new HashSet(); //pre-process - for (String scope : scopes) { - ScopeBean bean = new ScopeBean(scope); + for (String scope : context().container().configuration().authorizationProvider().getContexts()) { + ContextBean bean = new ContextBean(scope); switch (bean.type()) { case INFRASTRUCTURE: infrastructure = bean.name(); diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java index d2aa7f3..51cb27d 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/MetricsResource.java @@ -13,12 +13,6 @@ import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; -import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; -import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; -import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; -import io.micrometer.core.instrument.binder.system.ProcessorMetrics; -import io.micrometer.prometheus.PrometheusConfig; import io.micrometer.prometheus.PrometheusMeterRegistry; public class MetricsResource extends ApiResource { diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java index 58b6182..0ac19c8 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/ProfileResource.java @@ -9,7 +9,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.resources.gcore.Resources; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; @@ -35,7 +34,8 @@ public class ProfileResource extends ApiResource { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - Resources.marshal(context().profile(),resp.getWriter()); + //Resources.marshal(context().profile(),resp.getWriter()); + //TODO: return something to show } } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java deleted file mode 100644 index 4c57d0a..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileBuilder.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.gcube.smartgears.handlers.application.lifecycle; - -import java.net.URI; -import java.util.Arrays; -import java.util.Calendar; -import java.util.List; - -import javax.servlet.ServletRegistration; - -import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.context.application.ApplicationContext; - -public class ProfileBuilder { - - private static List servletExcludes = Arrays.asList("default","jsp"); - - // private static final Logger log = LoggerFactory.getLogger(ProfileBuilder.class); - - private ApplicationContext context; - - public ProfileBuilder(ApplicationContext context) { - this.context = context; - } - - public void fill(GCoreEndpoint endpoint) { - - - ApplicationConfiguration configuration = context.configuration(); - ContainerConfiguration container = context.container().configuration(); - - - endpoint.profile() - .description(configuration.description()) - .serviceName(configuration.name()) - .serviceClass(configuration.serviceClass()) - .version(configuration.version()) - .serviceId(configuration.name() + configuration.serviceClass() + configuration.version()) - .ghnId(context.container().profile().id()); - - endpoint.profile().newDeploymentData() - .activationTime(Calendar.getInstance()) - .status((context.lifecycle().state().remoteForm())); - - endpoint.profile().endpoints().clear(); - - String baseAddress; - if (configuration.proxied()){ - String protocol = configuration.proxyAddress().getProtocol(); - String port = configuration.proxyAddress().getPort()!=null?":"+configuration.proxyAddress().getPort():""; - - baseAddress=String.format("%s://%s%s%s", protocol , configuration.proxyAddress().getHostname(), port,context.application().getContextPath()); - } else { - String protocol = container.protocol(); - int port = container.port(); - - baseAddress=String.format("%s://%s:%d%s", protocol , container.hostname(), port,context.application().getContextPath()); - } - - for (ServletRegistration servlet : context.application().getServletRegistrations().values()) - if (!servletExcludes.contains(servlet.getName())) - for (String mapping : servlet.getMappings()) { - String address = baseAddress+(mapping.endsWith("*")?mapping.substring(0,mapping.length()-2):mapping); - endpoint.profile().endpoints().add().nameAndAddress(servlet.getName(),URI.create(address)); - } - - - } - -} diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java index 2418054..dcff68e 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java @@ -109,8 +109,6 @@ public class ProfileManager extends ApplicationLifecycleHandler { @Observes({ activation, stop, failure }) void onChanged(ApplicationLifecycle lc) { - GCoreEndpoint profile = context.profile(); - profile.profile().deploymentData().status(lc.state().remoteForm()); log.debug("moving app {} to {}",context.name(), lc.state().remoteForm()); diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java deleted file mode 100644 index 1aad5e3..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ServicePublisher.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.gcube.smartgears.handlers.application.lifecycle; - -import java.util.List; -import java.util.Set; - -import org.gcube.common.resources.gcore.GCoreEndpoint; -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.AbstractProfilePublisher; -import org.gcube.smartgears.handlers.ProfileEvents; - -/** - * Publishes the current resource profile of the application. - *

- *Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update()}. - * - * - * @author Fabio Simeoni - * - */ -public class ServicePublisher extends AbstractProfilePublisher { - - private final ApplicationContext context; - - public ServicePublisher(ApplicationContext context) { - super(); - this.context = context; - } - - - protected void sharePublished(HostingNode profile) { - context.events().fire(profile,ProfileEvents.published); - } - - - @Override - protected GCoreEndpoint getProfile() { - return context.profile(); - } - - - @Override - protected boolean isRoot() { - return context.container().configuration().mode()!=Mode.root; - } - - - @Override - protected void sharePublished(GCoreEndpoint profile) { - context.events().fire(profile,ProfileEvents.published); - } - - - @Override - protected Set getAllowedContexts() { - return context.container().configuration().authorizationProvider().getContexts(); - } -} - - diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 3766cdd..09bd236 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -7,8 +7,8 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.inv import javax.xml.bind.annotation.XmlRootElement; -import org.gcube.common.scope.impl.ScopeBean; -import org.gcube.common.scope.impl.ScopeBean.Type; +import org.gcube.common.security.ContextBean; +import org.gcube.common.security.ContextBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.GCubeSecret; @@ -89,7 +89,7 @@ public class RequestValidator extends RequestHandler { invalid_request_error.fire("call is unscoped"); } - ScopeBean bean = new ScopeBean(context); + ContextBean bean = new ContextBean(context); ContainerConfiguration conf = appContext.container().configuration(); if (!conf.allowedContexts().contains(context) && diff --git a/src/main/java/org/gcube/smartgears/publishing/Publisher.java b/src/main/java/org/gcube/smartgears/publishing/Publisher.java new file mode 100644 index 0000000..6d30126 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/publishing/Publisher.java @@ -0,0 +1,15 @@ +package org.gcube.smartgears.publishing; + +import org.gcube.smartgears.configuration.application.ApplicationConfiguration; +import org.gcube.smartgears.configuration.container.ContainerConfiguration; + +public interface Publisher { + + boolean publishContainer(ContainerConfiguration container, String ... contexts); + + boolean publishApplication(ApplicationConfiguration application, String ... contexts); + + boolean unpublishContainer(ContainerConfiguration container, String ... contexts); + + boolean unpublishApplication(ApplicationConfiguration application, String ... contexts); +} From 8030b049d02dcaf0f17872a8375df7d557d6fadc Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 10 Jun 2022 17:08:44 +0200 Subject: [PATCH 20/49] Publishing externalized to libraries in classpath --- pom.xml | 6 + .../java/org/gcube/smartgears/Constants.java | 2 +- .../application/ApplicationConfiguration.java | 3 - .../ApplicationConfigurationBinder.java | 4 +- .../BridgedApplicationConfiguration.java | 10 - .../DefaultApplicationConfiguration.java | 13 - .../ContainerConfigurationBinder.java | 6 +- .../context/container/ContainerContext.java | 5 - .../handlers/AbstractProfilePublisher.java | 116 ------ ...er.java => ApplicationProfileManager.java} | 182 +++------ .../lifecycle/ContainerProfileManager.java | 208 ++++++++++ .../lifecycle/ContainerPublisher.java | 54 --- .../lifecycle/LinuxDistributionInfo.java | 93 ----- .../container/lifecycle/ProfileBuilder.java | 375 ------------------ .../lifecycle/ProfileContainerManager.java | 291 -------------- .../managers/ApplicationManager.java | 9 +- .../smartgears/provider/DefaultProvider.java | 55 ++- .../smartgears/provider/OfflinePublisher.java | 56 --- .../gcube/smartgears/provider/Provider.java | 4 +- .../smartgears/publishing/Publisher.java | 14 +- .../SmartgearsProfilePublisher.java | 5 + .../DefaultAuthorizationProvider.java | 17 +- src/test/java/utils/TestProvider.java | 11 +- src/test/resources/container.ini | 2 +- 24 files changed, 348 insertions(+), 1193 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java rename src/main/java/org/gcube/smartgears/handlers/application/lifecycle/{ProfileManager.java => ApplicationProfileManager.java} (60%) create mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java delete mode 100644 src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java delete mode 100644 src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java create mode 100644 src/main/java/org/gcube/smartgears/publishing/SmartgearsProfilePublisher.java diff --git a/pom.xml b/pom.xml index cca1843..562539a 100644 --- a/pom.xml +++ b/pom.xml @@ -42,6 +42,12 @@ + + org.reflections + reflections + 0.9.10 + + org.gcube.common diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index 1fb9e88..3db496f 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -1,7 +1,7 @@ package org.gcube.smartgears; import org.gcube.smartgears.extensions.resource.RemoteResource; -import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; +import org.gcube.smartgears.handlers.application.request.RequestAccounting; import org.gcube.smartgears.handlers.application.request.RequestValidator; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index bcfb21a..4b9bbaf 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -115,10 +115,7 @@ public interface ApplicationConfiguration { */ ApplicationConfiguration persistence(PersistenceWriter manager); - void authorizedContexts(Set authorizedContexts); - Set authorizedContexts(); - /** * Validates this configuration. * diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java index 3f0380d..e12e04d 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -17,7 +17,7 @@ import javax.xml.bind.JAXBException; import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; -import org.gcube.smartgears.handlers.application.lifecycle.ProfileManager; +import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager; import org.gcube.smartgears.handlers.application.request.RequestAccounting; import org.gcube.smartgears.handlers.application.request.RequestValidator; @@ -75,7 +75,7 @@ public class ApplicationConfigurationBinder { List lifecycleHandlers = new LinkedList(); //ADDING BASE Handler (order is important) - lifecycleHandlers.add(new ProfileManager()); + lifecycleHandlers.add(new ApplicationProfileManager()); //TODO scan ApplicationLifecycleHandler form classloader diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java index 64414a5..7db8345 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java @@ -134,16 +134,6 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration return application.proxyAddress(proxyaddress); } - @Override - public void authorizedContexts(Set authorizedContexts) { - application.authorizedContexts(authorizedContexts); - - } - - @Override - public Set authorizedContexts() { - return application.authorizedContexts(); - } } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java index 0427fff..d211dcf 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java @@ -57,8 +57,6 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElementRef Set includes= new LinkedHashSet(); - Set authorizedContexts; - @NotNull @IsValid private PersistenceWriter persistenceManager; @@ -169,17 +167,6 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration this.proxyAddress = proxyaddress; return this; } - - @Override - public void authorizedContexts(Set authorizedContexts) { - this.authorizedContexts = authorizedContexts; - } - - - @Override - public Set authorizedContexts() { - return this.authorizedContexts; - } @Override public void validate() { diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 01919b9..7f34680 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -11,7 +11,7 @@ import java.util.stream.Collectors; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; -import org.gcube.smartgears.handlers.container.lifecycle.ProfileContainerManager; +import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager; import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; @@ -156,9 +156,9 @@ public class ContainerConfigurationBinder { LinkedList handlers = new LinkedList(); - //ADDING BASE Handler (order is important) + //ADDING BASE Handlers (order is important) handlers.add(new AccountingManager()); - handlers.add(new ProfileContainerManager()); + handlers.add(new ContainerProfileManager()); handlers.addAll(scanForContainerHadlers(classloader)); diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index c1f043b..3eecf4a 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -22,11 +22,6 @@ public interface ContainerContext { */ ContainerConfiguration configuration(); - /** - * Returns the resource profile of a given type of the container. - * @return the profile - */ - HostingNode profile(); /** * Returns the lifecycle of the container diff --git a/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java b/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java deleted file mode 100644 index 9bf4931..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/AbstractProfilePublisher.java +++ /dev/null @@ -1,116 +0,0 @@ -package org.gcube.smartgears.handlers; - -import static org.gcube.smartgears.utils.Utils.notEmpty; -import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Set; - -import org.gcube.common.resources.gcore.Resource; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.smartgears.provider.ProviderFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractProfilePublisher

implements ProfilePublisher { - - private static final Logger log = LoggerFactory.getLogger(AbstractProfilePublisher.class); - - //the underlying IS publisher - private final ScopedPublisher publisher; - - //private AuthorizationProvider authProvider ; - - public AbstractProfilePublisher() { - this.publisher=ProviderFactory.provider().publisher(); - //this.authProvider = ProviderFactory.provider().authorizationProvider(); - } - - protected abstract P getProfile(); - protected abstract boolean isRoot(); - protected abstract void sharePublished(P profile); - protected abstract Set getAllowedContexts(); - - /** - * Removes the application from one or more scopes. - * @param scopes the scopes - */ - public void removeFrom(Collection contexts) { - P profile = getProfile(); - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - try{//This classloader set is needed for the jaxb context - if (isRoot()) - Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); - profile = publisher.remove(profile, new ArrayList(contexts)); - - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - if (isRoot()) - Thread.currentThread().setContextClassLoader(contextCL); - } - log.debug("after remove application profile contains scopes {}",profile.scopes().asCollection()); - sharePublished(profile); - } - - - public void addToAll(){ - this.addTo(getAllowedContexts()); - } - - /** - * Adds for the first time the current resource profile of the application in one or more scopes. - * @param contexts the contexts - */ - public void addTo(Collection contexts) { - notEmpty("contexts",contexts); - - P profile = getProfile(); - - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - try{//This classloader set is needed for the jaxb context - if (isRoot()) Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); - profile = publisher.create(profile, new ArrayList(contexts)); - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - if (isRoot()) Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - log.debug("shared profile with scopes {}", profile.scopes().asCollection()); - } - - - - public void update() { - P profile = getProfile(); - ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); - - log.debug("using context {}",contextCL.getClass().getSimpleName()); - - try{//This classloader set is needed for the jaxb context - - if (isRoot()) - Thread.currentThread().setContextClassLoader(AbstractProfilePublisher.class.getClassLoader()); - profile = publisher.update(profile); - - } catch (Exception e) { - rethrowUnchecked(e); - } finally{ - if (isRoot()) - Thread.currentThread().setContextClassLoader(contextCL); - } - - sharePublished(profile); - } - - -} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java similarity index 60% rename from src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java rename to src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index dcff68e..57477ea 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -2,36 +2,30 @@ package org.gcube.smartgears.handlers.application.lifecycle; import static org.gcube.common.events.Observes.Kind.resilient; import static org.gcube.smartgears.Constants.profile_management; -import static org.gcube.smartgears.Constants.profile_property; import static org.gcube.smartgears.handlers.ProfileEvents.addToContext; import static org.gcube.smartgears.handlers.ProfileEvents.changed; -import static org.gcube.smartgears.handlers.ProfileEvents.published; import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext; import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.activation; import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.failure; import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.stop; -import static org.gcube.smartgears.lifecycle.application.ApplicationState.failed; import java.util.Collections; +import java.util.List; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.TimeUnit; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.events.Observes; import org.gcube.common.events.Observes.Kind; -import org.gcube.common.resources.gcore.GCoreEndpoint; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.Property; import org.gcube.smartgears.context.application.ApplicationContext; -import org.gcube.smartgears.handlers.OfflineProfilePublisher; -import org.gcube.smartgears.handlers.ProfilePublisher; import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.application.ApplicationState; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.provider.ProviderFactory; +import org.gcube.smartgears.publishing.Publisher; import org.gcube.smartgears.utils.Utils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -55,25 +49,23 @@ import org.slf4j.LoggerFactory; * @see ProfileBuilder * @see ProfilePublisherImpl */ -@XmlRootElement(name = profile_management) -public class ProfileManager extends ApplicationLifecycleHandler { +public class ApplicationProfileManager extends ApplicationLifecycleHandler { - Logger log = LoggerFactory.getLogger(ProfileManager.class); + Logger log = LoggerFactory.getLogger(ApplicationProfileManager.class); private ApplicationContext context; - private ProfileBuilder builder; - private ProfilePublisher publisher; - private ScheduledFuture periodicUpdates; + private List publishers = ProviderFactory.provider().publishers(); + + @Override public void onStart(ApplicationLifecycleEvent.Start e) { context = e.context(); - builder = new ProfileBuilder(context); activated(); - + schedulePeriodicUpdates(); // note we don't fire profile events, but wait for the final startup // outcome which @@ -89,16 +81,12 @@ public class ProfileManager extends ApplicationLifecycleHandler { private void activated(){ - GCoreEndpoint profile = loadOrCreateProfile(); - - share(profile); - - publisher = context.container().configuration().mode()!=Mode.offline? - new ServicePublisher(context): - new OfflineProfilePublisher(); - - + + publishers = context.container().configuration().mode()!=Mode.offline? + ProviderFactory.provider().publishers(): + Collections.emptyList(); registerObservers(); + schedulePeriodicUpdates(); } // helpers @@ -109,84 +97,76 @@ public class ProfileManager extends ApplicationLifecycleHandler { @Observes({ activation, stop, failure }) void onChanged(ApplicationLifecycle lc) { - profile.profile().deploymentData().status(lc.state().remoteForm()); - log.debug("moving app {} to {}",context.name(), lc.state().remoteForm()); // since we do not know the observers, they will deal with // failures and their consequences // any that comes back will be logged in this event thread - context.events().fire(profile, changed); + context.events().fire(context, changed); } + /* @Observes(value = published) void shareAfterPublish(GCoreEndpoint profile) { share(profile); // publish may produce a new profile instance - } + }*/ @Observes(value = changed, kind = Kind.safe) - void publishAfterChange(GCoreEndpoint profile) { + void publishAfterChange(ApplicationContext context) { - boolean firstPublication = profile.scopes().isEmpty(); //if we've failed before first publication do not try to publish //(we may well have failed there) - try { + for (Publisher publisher: publishers) + try { + publisher.publishApplication(context, + context.container().configuration().authorizationProvider().getContexts()); + }catch (Exception e) { - if (firstPublication) { - if (context.lifecycle().state()!= failed) - publishFirstTime(profile); + log.error("cannot publish {} with publisher type {} (see details)",context.name(), publisher.getClass().getCanonicalName(), e); + + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); } - else{ - log.debug("update app {} profile",context.name()); - publisher.update(); // if successful, triggers share. - } - } - catch (Exception e) { - - log.error("cannot publish "+context.name()+" (see details)", e); - - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); - } - - } @Observes(value = addToContext) - void addTo(String token) { - try { - log.trace("publishing application in new context"); - publisher.addTo(Collections.singleton(token)); - publisher.update(); - }catch (Exception e) { + void addTo(String scope) { + for (Publisher publisher: publishers) + try { + log.debug("publishing application in context {}", scope); + publisher.publishApplication(context, + Collections.singleton(scope)); - log.error("cannot add token {} (see details)",token, e); + }catch (Exception e) { - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); - } + log.error("cannot add context {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); + + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); + } } - + @Observes(value = removeFromContext) - void removeFrom(String token) { + void removeFrom(String scope) { + for (Publisher publisher: publishers) try { - log.trace("unpublishing application from context"); - publisher.removeFrom(Collections.singleton(token)); - publisher.update(); + log.debug("unpublishing application from scope {}", scope); + publisher.unpublishApplication(context, + Collections.singleton(scope)); }catch (Exception e) { - log.error("cannot remove token {} (see details)",token, e); + log.error("cannot remove scope {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); // since we've failed no published event is fired and profile // will not be stored. @@ -199,52 +179,6 @@ public class ProfileManager extends ApplicationLifecycleHandler { }); } - - private void share(GCoreEndpoint profile) { - - log.trace("sharing profile for {}", context.name()); - - context.properties().add(new Property(profile_property, profile)); - } - - private void publishFirstTime(GCoreEndpoint profile) { - - try { - - publisher.addToAll(); - - } catch (Exception e) { - log.warn("publishing failed",e); - } - } - - private GCoreEndpoint loadOrCreateProfile() { - - return create(); - } - - private GCoreEndpoint create() { - - log.info("creating profile for {}", context.name()); - - try { - - GCoreEndpoint profile = new GCoreEndpoint(); - profile.setId(context.id()); - - builder.fill(profile); - - return profile; - - } catch (RuntimeException e) { - - // this is a critical startup failure: it will fail the application - throw new RuntimeException("cannot create profile for " + context.name(), e); - - } - - } - private void schedulePeriodicUpdates() { // register to cancel updates @@ -268,12 +202,10 @@ public class ProfileManager extends ApplicationLifecycleHandler { final Runnable updateTask = new Runnable() { public void run() { - GCoreEndpoint profile = context.profile(); - //if handling of event generates failures these will be reported //for resilience we do not fail the application - log.trace("firing change event on application {} profile", context.name()); - context.events().fire(profile,changed); + log.trace("firing change event on application {} ", context.name()); + context.events().fire(context,changed); } }; @@ -292,7 +224,7 @@ public class ProfileManager extends ApplicationLifecycleHandler { periodicUpdates=null; } catch(Exception e) { - log.warn("could not stop periodic updates of application {} profile", context.name(),e); + log.warn("could not stop periodic updates of application {}", context.name(),e); } } } @@ -300,8 +232,8 @@ public class ProfileManager extends ApplicationLifecycleHandler { }); } - - + + @Override public String toString() { return profile_management; diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java new file mode 100644 index 0000000..c29388e --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -0,0 +1,208 @@ +package org.gcube.smartgears.handlers.container.lifecycle; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.gcube.common.events.Observes.Kind.critical; +import static org.gcube.common.events.Observes.Kind.resilient; +import static org.gcube.smartgears.Constants.profile_management; +import static org.gcube.smartgears.handlers.ProfileEvents.addToContext; +import static org.gcube.smartgears.handlers.ProfileEvents.changed; +import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.activation; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.failure; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.part_activation; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.shutdown; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.stop; +import static org.gcube.smartgears.lifecycle.container.ContainerState.active; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ScheduledFuture; + +import org.gcube.common.events.Observes; +import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.handlers.container.ContainerHandler; +import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; +import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.provider.ProviderFactory; +import org.gcube.smartgears.publishing.Publisher; +import org.gcube.smartgears.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * Manages the resource profile of the application. + *

+ * + * The manager: + * + *

    + *
  • creates the profile when the application starts for the first time; + *
  • loads the profile when the application restarts; + *
  • publishes the profile when the application becomes active, and at any + * lifecycle change thereafter; + *
  • stores the profile locally after each publication; + *
+ * + * @author Fabio Simeoni + * @see ProfileBuilder + * @see ProfilePublisherImpl + */ +public class ContainerProfileManager extends ContainerHandler { + + Logger log = LoggerFactory.getLogger(ContainerProfileManager.class); + + private ContainerContext context; + private ScheduledFuture periodicUpdates; + + private List publishers; + + + @Override + public void onStart(ContainerLifecycleEvent.Start e) { + + context = e.context(); + + activated(); + + schedulePeriodicUpdates(); + // note we don't fire profile events, but wait for the final startup + // outcome which + // will result in a state change. only then we publish and store the + // profile + // this avoids the redundancy and performance penalty of storing and + // publishing multiple + // times in rapid succession (which would be correct). Revise if proves + // problematic in corner + // cases. + + } + + + private void activated(){ + publishers = context.configuration().mode()!=Mode.offline? + ProviderFactory.provider().publishers(): + Collections.emptyList(); + registerObservers(); + schedulePeriodicUpdates(); + } + + private void registerObservers() { + context.events().subscribe(new Object() { + @Observes({ activation, part_activation, shutdown, stop, failure }) + void onChanged(ContainerLifecycle lc) { + + // since we do not know the observers, they will deal with failures and their consequences + // any that comes back will be logged in this event thread + context.events().fire(context, changed); + } + + @Observes(value = changed, kind = critical) + void publishAfterChange(ContainerContext context) { + log.info("Publish after profile Change event called"); + //if we've failed before first publication do not try to publish + //(we may well have failed there) + for (Publisher publisher: publishers) + try { + publisher.publishContainer(context, + context.configuration().authorizationProvider().getContexts()); + }catch (Exception e) { + + log.error("cannot publish containar with publisher type {} (see details)", publisher.getClass().getCanonicalName(), e); + + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); + } + } + + @Observes(value = addToContext) + void addTo(String scope) { + for (Publisher publisher: publishers) + try { + log.trace("publishing container within new scope"); + publisher.publishContainer(context, + Collections.singleton(scope)); + + }catch (Exception e) { + + log.error("cannot add container to {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); + + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); + } + + } + + @Observes(value = removeFromContext) + void removeFrom(String scope) { + for (Publisher publisher: publishers) + try { + log.trace("unpublishing container from context {}", scope); + publisher.unpublishContainer(context, + Collections.singleton(scope)); + + }catch (Exception e) { + + log.error("cannot add container to {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); + + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); + } + } + }); + } + + + private void schedulePeriodicUpdates() { + // register to cancel updates + context.events().subscribe( + new Object() { + // we register it in response to lifecycle events so that we can stop and resume along with application + @Observes(value = { activation, part_activation }, kind = resilient) + synchronized void restartPeriodicUpdates(ContainerLifecycle lc) { + //already running + if (periodicUpdates!=null) + return; + if (lc.state()==active) + log.info("scheduling periodic updates of container profile"); + else + log.info("resuming periodic updates of container profile"); + final Runnable updateTask = new Runnable() { + public void run() { + context.events().fire(context,changed); + } + }; + periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, 3, context.configuration() + .publicationFrequency(), SECONDS); + } + @Observes(value = { stop, failure, shutdown }, kind = resilient) + synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) { + if (periodicUpdates != null){ + log.trace("stopping periodic updates of container profile"); + try { + periodicUpdates.cancel(true); + periodicUpdates=null; + } + catch(Exception e) { + log.warn("could not stop periodic updates of container profile",e); + } + } + } + }); + } + @Override + public String toString() { + return profile_management; + } +} + diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java deleted file mode 100644 index a883ba7..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerPublisher.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.gcube.smartgears.handlers.container.lifecycle; - -import java.util.List; -import java.util.Set; - -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.handlers.AbstractProfilePublisher; -import org.gcube.smartgears.handlers.ProfileEvents; - -/** - * Publishes the resource profile of the container. - *

- * Distinguishes publication in new scopes ({@link #addTo(List)} from publication updates in existing scopes ({@link #update(List)}. - * - * @author Fabio Simeoni - * - */ -public class ContainerPublisher extends AbstractProfilePublisher { - - - private final ContainerContext context; - - public ContainerPublisher(ContainerContext context) { - super(); - this.context = context; - } - - - protected void sharePublished(HostingNode profile) { - context.events().fire(profile,ProfileEvents.published); - } - - - @Override - protected HostingNode getProfile() { - return context.profile(); - } - - - @Override - protected boolean isRoot() { - return context.configuration().mode()!=Mode.root; - } - - - @Override - protected Set getAllowedContexts() { - return context.configuration().allowedContexts(); - } - - -} diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java deleted file mode 100644 index 8fe8bc2..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/LinuxDistributionInfo.java +++ /dev/null @@ -1,93 +0,0 @@ -package org.gcube.smartgears.handlers.container.lifecycle; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.util.HashMap; -import java.util.Map; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Luca Frosini (ISTI-CNR) - */ -public class LinuxDistributionInfo { - - private static final Logger logger = LoggerFactory.getLogger(LinuxDistributionInfo.class); - - public static final String LSB_RELEASE_COMMAND = "lsb_release -a"; - public static final String OS_RELEASE_FILE_PATH = "/etc/os-release"; - - protected Map info; - - protected Map getInfoViaLsbReleaseCommand() throws IOException { - logger.trace("Going to exec {}", LSB_RELEASE_COMMAND); - Process process = Runtime.getRuntime().exec(LSB_RELEASE_COMMAND); - BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())); - Map map = parseBufferedReader(bufferedReader); - bufferedReader.close(); - return map; - } - - private Map parseBufferedReader(BufferedReader bufferedReader) throws IOException { - Map map = new HashMap<>(); - String line = ""; - while ((line = bufferedReader.readLine()) != null) { - String[] nameValue = parseLine(line); - map.put(nameValue[0], nameValue[1]); - } - return map; - } - - private String[] parseLine(String line) { - String[] splitted = line.split("="); - if (splitted.length < 2) { - splitted = line.split(":"); - } - String[] ret = new String[2]; - ret[0] = splitted[0].trim(); - ret[1] = splitted[1].trim().replace("\"", ""); - return ret; - } - - private Map getInfoViaFile(File file) throws IOException { - logger.trace("Going to read file {}", file.getAbsolutePath()); - BufferedReader bufferedReader = new BufferedReader(new FileReader(file)); - Map map = parseBufferedReader(bufferedReader); - bufferedReader.close(); - return map; - - } - - protected Map getInfoViaOsReleaseFile() throws IOException { - File osReleaseFile = new File(OS_RELEASE_FILE_PATH); - return getInfoViaFile(osReleaseFile); - } - - private Map retriveInfo() { - try { - return getInfoViaLsbReleaseCommand(); - } catch (IOException e) { - - } - - try { - return getInfoViaOsReleaseFile(); - }catch (IOException e) { - - } - - return null; - } - - public Map getInfo() { - if (info == null) { - info = retriveInfo(); - } - return info; - } - -} diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java deleted file mode 100644 index 701ff8d..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileBuilder.java +++ /dev/null @@ -1,375 +0,0 @@ -package org.gcube.smartgears.handlers.container.lifecycle; - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.math.BigDecimal; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.HashMap; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.GHNType; -import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.Processor; -import org.gcube.common.resources.gcore.HostingNode.Profile.NodeDescription.Variable; -import org.gcube.common.resources.gcore.utils.Group; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.provider.ProviderFactory; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * @author Fabio Simeoni - * @author Luca Frosini (ISTI - CNR) - * - */ -public class ProfileBuilder { - - private static Logger log = LoggerFactory.getLogger(ProfileBuilder.class); - - private ContainerContext context; - - public ProfileBuilder(ContainerContext context) { - this.context = context; - } - - public HostingNode create() { - - HostingNode node = new HostingNode(); - - ContainerConfiguration cfg = context.configuration(); - - node.newProfile().infrastructure(cfg.infrastructure()); - - addSiteTo(node); - - String ip = "not resolved"; - try { - ip = InetAddress.getLocalHost().getHostAddress(); - } catch (UnknownHostException e) { - log.warn("unable to detect the IP address of the host"); - } - - node.profile().newDescription().activationTime(Calendar.getInstance()).name(cfg.hostname() + ":" + cfg.port()); - - node.profile().description().networkAdapters().add().mtu(0).name("local-adapter").ipAddress(ip).inboundIP("") - .outboundIP(""); - - node.profile().description().newOperatingSystem().name(System.getProperty("os.name")) - .version(System.getProperty("os.version")).release(""); - - node.profile().description().newArchitecture().platformType(System.getProperty("os.arch")).smpSize(0) - .smtSize(0); - - node.profile().newSite().domain("It").country("It").location("Rome").latitude("1").longitude("1"); - - ArrayList> info = cpuInfo(); - - Group processors = node.profile().description().processors(); - - for (HashMap map : info) - - processors.add().bogomips(new BigDecimal(map.get("bogomips"))) - .clockSpeedMhz(new BigDecimal(map.get("cpu_MHz"))).family(map.get("cpu_family")) - .modelName(map.get("model_name")).model(map.get("model")).vendor(map.get("vendor_id")) - .cacheL1(new Integer(map.get("cache_size"))).cacheL1D(0).cacheL1I(0).cacheL2(0); - - addVariablesTo(node); - - update(node,false); - - node.profile().description().type(GHNType.Static); - // String type = (String) context.getProperty(GHNContext.GHN_TYPE, false); - // if (type.compareToIgnoreCase(Type.DYNAMIC.toString()) == 0) description.setType(Description.Type.Dynamic); - // else if (type.compareToIgnoreCase(Type.STATIC.toString()) == 0) description.setType(Description.Type.Static); - // else if (type.compareToIgnoreCase(Type.SELFCLEANING.toString()) == 0) - // description.setType(Description.Type.Selfcleaning); - // - // file system - node.profile().description().localFileSystems().add().name("").type("").readOnly(false) - .root("/"); - - return node; - } - - @SuppressWarnings("all") - private ArrayList> cpuInfo() { - - ArrayList> map = new ArrayList>(); - - File file = new File("/proc/cpuinfo"); - - if (!file.exists()) { - log.warn("cannot acquire CPU info (no /proc/cpuinfo)"); - return map; - } - - BufferedReader input = null; - - try { - input = new BufferedReader(new FileReader(file)); - - String line = null; - - HashMap currentProcessor = null; - - while ((line = input.readLine()) != null) { - - if ((line.startsWith("processor"))) { // add the current processor to the map - - if (currentProcessor != null) - map.add((HashMap) currentProcessor.clone()); - - currentProcessor = new HashMap(); - } - - try { - if (line.contains("vendor_id")) - currentProcessor.put("vendor_id", line.split(":")[1].trim()); - } catch (Exception ex) { - } - try { - if (line.contains("cpu family")) - currentProcessor.put("cpu_family", line.split(":")[1].trim()); - } catch (Exception ex) { - } - try { - if ((line.contains("model\t")) || (line.contains("model\b"))) - currentProcessor.put("model", line.split(":")[1].trim()); - } catch (Exception ex) { - } - try { - if (line.contains("model name")) - currentProcessor.put("model_name", line.split(":")[1].trim()); - } catch (Exception ex) { - } - try { - if (line.contains("cpu MHz")) - currentProcessor.put("cpu_MHz", line.split(":")[1].trim()); - } catch (Exception ex) { - } - try { - if (line.contains("cache size")) - currentProcessor.put("cache_size", line.split(":")[1].trim().split(" ")[0]); - } catch (Exception ex) { - } - try { - if (line.contains("bogomips")) - currentProcessor.put("bogomips", line.split(":")[1].trim()); - } catch (Exception ex) { - } - } - - if (currentProcessor != null) - map.add(currentProcessor); - - } catch (Exception e) { - - log.warn("unable to acquire CPU info", e); - - } finally { - - if (input != null) - try { - input.close(); - } catch (IOException e) { - log.warn("unable to close stream", e); - } - } - return map; - } - - private long getFreeSpace() { - long free = 0; - try { - free = context.configuration().persistence().getFreeSpace()/1024; - } catch (Exception ioe) { - log.warn("unable to detect the free space on the disk", ioe); - } - return free; - } - - public void update(HostingNode node,boolean onLoad) { - - ContainerConfiguration cfg = context.configuration(); - - if (onLoad) { - - log.info("updating ghn profile"); - - node.profile().description().activationTime(Calendar.getInstance()).name(cfg.hostname() + ":" + cfg.port()); - - addVariablesTo(node); - - addSiteTo(node); - - } - - node.profile().description().status(context.lifecycle().state().remoteForm()); - - Map mem = memoryUsage(); - - node.profile().description().newMainMemory().ramAvailable(mem.get("MemoryAvailable")) - .ramSize(mem.get("MemoryTotalSize")).virtualAvailable(mem.get("VirtualAvailable")) - .virtualSize(mem.get("VirtualSize")); - - node.profile().description().localAvailableSpace(getFreeSpace()); - - node.profile().description().uptime(uptime()); - - node.profile().description().lastUpdate(Calendar.getInstance()); - - Map loads = loadStatistics(); - - node.profile().description().newLoad().lastMin(loads.get("1min") == null ? 0 : loads.get("1min")) - .last5Mins(loads.get("5mins") == null ? 0 : loads.get("5mins")) - .last15Mins(loads.get("15mins") == null ? 0 : loads.get("15mins")); - - } - - private void addSiteTo(HostingNode node) { - - ContainerConfiguration cfg = context.configuration(); - - node.profile().newSite().country(cfg.site().getCountry()).location(cfg.site().getLocation()) - .latitude(cfg.site().getLatitude()).longitude(cfg.site().getLongitude()).domain(domainIn(cfg.hostname())); - } - - private void addVariablesTo(HostingNode node) { - - ContainerConfiguration cfg = context.configuration(); - - Group variables = node.profile().description().environmentVariables(); - - // Cleaning variables to avoid duplicates - variables.removeAll(node.profile().description().environmentVariables()); - - Map map = new HashMap(); - map.putAll(cfg.properties()); - map.putAll(System.getenv()); - - for (Map.Entry entry : map.entrySet()) { - String varname = entry.getKey(); - if ((varname.compareToIgnoreCase("CLASSPATH") == 0) || (varname.compareToIgnoreCase("PATH") == 0) - || (varname.contains("SSH")) || (varname.contains("MAIL")) - || (varname.compareToIgnoreCase("LS_COLORS") == 0)) - continue; - variables.add().keyAndValue(entry.getKey(), entry.getValue()); - } - - /* The following code is useless can be removed - Map envvars = new HashMap(); - for (String varname : envvars.keySet()) { - - // a bit of filtering - if ((varname.compareToIgnoreCase("CLASSPATH") == 0) || (varname.compareToIgnoreCase("PATH") == 0) - || (varname.contains("SSH")) || (varname.contains("MAIL")) - || (varname.compareToIgnoreCase("LS_COLORS") == 0)) - continue; - - variables.add().keyAndValue(varname, envvars.get(varname)); - } - */ - - - String osVersion = System.getProperty("os.name"); - if(osVersion.compareToIgnoreCase("Linux")==0) { - LinuxDistributionInfo linuxDistributionInfo = new LinuxDistributionInfo(); - Map info = linuxDistributionInfo.getInfo(); - for(String key : info.keySet()) { - variables.add().keyAndValue(key, info.get(key)); - } - } - - variables.add().keyAndValue("Java", System.getProperty("java.version")); - - SmartGearsConfiguration config = ProviderFactory.provider().smartgearsConfiguration(); - variables.add().keyAndValue("SmartGears",config.version()); - - variables.add().keyAndValue("ghn-update-interval-in-secs", String.valueOf(cfg.publicationFrequency())); - - } - - public String uptime() { - String lines = "", linetemp = null; - try { - Process p = Runtime.getRuntime().exec("uptime"); - p.waitFor(); - BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream())); - while ((linetemp = input.readLine()) != null) - lines += linetemp; - input.close(); - p.destroy(); - lines = lines.split(",")[0].split("up")[1].trim(); - } catch (Exception e) { - log.warn("unable to detect the uptime of this machine", e); - lines = "unable to detect"; - } - return lines; - } - - public Map loadStatistics() { - - Map result = new HashMap(); - try { - File loadadv = new File("/proc/loadavg"); - if (loadadv.exists()) { - Reader reader = new FileReader(loadadv); - int c; - StringBuilder content = new StringBuilder(); - while ((c = reader.read()) != -1) - content.append((char) c); - reader.close(); - Pattern p = Pattern.compile("^(.*?)\\s{1}(.*?)\\s{1}(.*?)\\s{1}(.*)$"); - Matcher matcher = p.matcher(content.toString()); - if ((matcher.matches()) && (matcher.groupCount() > 3)) { - result.put("1min", new Double(matcher.group(1))); - result.put("5mins", new Double(matcher.group(2))); - result.put("15mins", new Double(matcher.group(3).split("\\s")[0])); - } - } - } catch (Exception ioe) { - log.warn("unable to detect the load values of this machine", ioe); - } - return result; - } - - @SuppressWarnings("all") - public Map memoryUsage() { - Map map = new HashMap(); - java.lang.management.OperatingSystemMXBean mxbean = java.lang.management.ManagementFactory - .getOperatingSystemMXBean(); - com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean; - long freeMemory = sunmxbean.getFreePhysicalMemorySize() / 1048576; // in MB - long availableMemory = sunmxbean.getTotalPhysicalMemorySize() / 1048576; // in MB - map.put("MemoryAvailable", freeMemory); - map.put("MemoryTotalSize", availableMemory); - long ramVirtualAvailable = Runtime.getRuntime().freeMemory() / 1048576; // in MB - long ramVirtualSize = Runtime.getRuntime().totalMemory() / 1048576; // in MB - map.put("VirtualAvailable", ramVirtualAvailable); - map.put("VirtualSize", ramVirtualSize); - return map; - } - - private String domainIn(String hostname) { - Pattern pattern = Pattern.compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); - java.util.regex.Matcher regexMatcher = pattern.matcher(hostname); - if (regexMatcher.matches()) //it's an IP address, nothing to trim - return hostname; - String[] tokens = hostname.split("\\."); - if (tokens.length < 2) - return hostname; - else - return tokens[tokens.length-2]+ "." + tokens[tokens.length-1]; - } -} diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java deleted file mode 100644 index 62b4a62..0000000 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ProfileContainerManager.java +++ /dev/null @@ -1,291 +0,0 @@ -package org.gcube.smartgears.handlers.container.lifecycle; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.gcube.common.events.Observes.Kind.critical; -import static org.gcube.common.events.Observes.Kind.resilient; -import static org.gcube.smartgears.Constants.container_profile_property; -import static org.gcube.smartgears.Constants.profile_management; -import static org.gcube.smartgears.handlers.ProfileEvents.addToContext; -import static org.gcube.smartgears.handlers.ProfileEvents.changed; -import static org.gcube.smartgears.handlers.ProfileEvents.published; -import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext; -import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.activation; -import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.failure; -import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.part_activation; -import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.shutdown; -import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.stop; -import static org.gcube.smartgears.lifecycle.container.ContainerState.active; - -import java.util.Collections; -import java.util.concurrent.ScheduledFuture; - -import org.gcube.common.events.Observes; -import org.gcube.common.resources.gcore.HostingNode; -import org.gcube.smartgears.configuration.Mode; -import org.gcube.smartgears.context.Property; -import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.handlers.OfflineProfilePublisher; -import org.gcube.smartgears.handlers.ProfilePublisher; -import org.gcube.smartgears.handlers.container.ContainerHandler; -import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent.Start; -import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; -import org.gcube.smartgears.utils.Utils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * Manages the resource profile of the container. - *

- * - * The manager: - * - *

    - *
  • creates the profile when the container starts for the first time; - *
  • loads the profile when the container restarts; - *
  • publishes the profile when the container becomes active, and at any lifecycle change thereafter; - *
  • stores the profile locally after each publication; - *
- * - * @author Fabio Simeoni - * @see ProfileBuilder - */ -public class ProfileContainerManager extends ContainerHandler { - - private static Logger log = LoggerFactory.getLogger(ProfileContainerManager.class); - - private ContainerContext context; - - private ProfileBuilder builder; - private ProfilePublisher publisher; - - - private ScheduledFuture periodicUpdates; - - @Override - public void onStart(Start e) { - - context = e.context(); - builder = new ProfileBuilder(context); - - activated(); - - // note we don't fire profile events, but wait for the final startup response which - // will result in a state change. only then we publish and store the profile - // this avoids the redundancy and performance penalty of storing and publishing multiple - // times in rapid succession (which would be correct). Revise if proves problematic in corner - // cases. - - } - - private void activated(){ - HostingNode profile = loadOrCreateProfile(); - - share(profile); - - publisher = context.configuration().mode()!=Mode.offline? - new ContainerPublisher(context): - new OfflineProfilePublisher(); - - registerObservers(); - - schedulePeriodicUpdates(); - } - - private void registerObservers() { - - context.events().subscribe(new Object() { - - @Observes({ activation, part_activation, shutdown, stop, failure }) - void onChanged(ContainerLifecycle lc) { - - HostingNode profile = context.profile(); - - profile.profile().description().status(lc.state().remoteForm()); - - // since we do not know the observers, they will deal with failures and their consequences - // any that comes back will be logged in this event thread - context.events().fire(profile, changed); - - } - - - @Observes(value = published) - void shareAfterPublish(HostingNode profile) { - - share(profile); // publish may produce a new profile instance - - } - - @Observes(value = changed, kind = critical) - void publishAfterChange(HostingNode profile) { - log.info("Publish after profile Change event called"); - publish(profile); // if successful, triggers share and store. - - } - - @Observes(value = addToContext) - void addTo(String token) { - try { - log.trace("publishing container with new token"); - publisher.addTo(Collections.singleton(token)); - publisher.update(); - }catch (Exception e) { - - log.error("cannot add token {} (see details)",token, e); - - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); - } - - } - - @Observes(value = removeFromContext) - void removeFrom(String token) { - try { - log.trace("unpublishing container with new token"); - publisher.removeFrom(Collections.singleton(token)); - publisher.update(); - }catch (Exception e) { - - log.error("cannot remove token {} (see details)",token, e); - - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); - } - - } - }); - } - - private HostingNode loadOrCreateProfile() { - - return createProfile(); - - } - - private void share(HostingNode profile) { - - log.trace("sharing container profile"); - context.properties().add(new Property(container_profile_property, profile)); - } - - private HostingNode createProfile() { - - log.info("creating container profile"); - - try { - HostingNode node = builder.create(); - node.setId(context.id()); - return node; - } catch (Throwable e) { - - // this is a critical startup failure: it will fail the application - throw new RuntimeException("cannot create container profile", e); - - } - - } - - private void publish(HostingNode profile) { - - //ContainerConfiguration configuration = context.configuration(); - - // first-publication vs. routine publication: when we delete scopes let's make sure there is - // at least one left of it will be re-triggered - boolean firstPublication = profile.scopes().isEmpty(); - - try { - - if (firstPublication) - publisher.addToAll(); - else - publisher.update(); - - } catch (Exception e) { - - log.error("cannot publish container (see details)", e); - - // since we've failed no published event is fired and profile will not be stored. - // we do it manually to ensure we leave some local trace of the changed profile. - //store(profile); - - } - } - - private void schedulePeriodicUpdates() { - - // register to cancel updates - context.events().subscribe( - - new Object() { - - // we register it in response to lifecycle events so that we can stop and resume along with application - @Observes(value = { activation, part_activation }, kind = resilient) - synchronized void restartPeriodicUpdates(ContainerLifecycle lc) { - - //already running - if (periodicUpdates!=null) - return; - - if (lc.state()==active) - log.info("scheduling periodic updates of container profile"); - - else - log.info("resuming periodic updates of container profile"); - - final Runnable updateTask = new Runnable() { - public void run() { - HostingNode profile = context.profile(); - - try { - builder.update(profile, false); - } - catch(Exception e) { - //we may fail in the update of the profile - log.error("cannot complete periodic update of container profile",e); - } - - //if handling of event generates failures these will be reported - //for resilience we do not fail the application - log.trace("firing change event on container profile"); - context.events().fire(profile,changed); - } - }; - - periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, 3, context.configuration() - .publicationFrequency(), SECONDS); - - } - - @Observes(value = { stop, failure, shutdown }, kind = resilient) - synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) { - - if (periodicUpdates != null){ - log.trace("stopping periodic updates of container profile"); - - try { - periodicUpdates.cancel(true); - periodicUpdates=null; - } - catch(Exception e) { - log.warn("could not stop periodic updates of container profile",e); - } - } - } - - }); - - } - - @Override - public String toString() { - return profile_management; - } -} diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index 537e650..579301f 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -23,7 +23,6 @@ import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration; import org.gcube.common.events.Observes; -import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.context.application.ApplicationContext; @@ -69,11 +68,8 @@ public class ApplicationManager { for (Entry servlet : application.getServletRegistrations().entrySet()) log.trace("servlet {} : {} {} ", application.getServletContextName(),servlet.getKey(), servlet.getValue().getMappings()); - if (context.container().configuration().mode()!=Mode.offline) { - context.configuration().authorizedContexts(context.container().configuration().allowedContexts()); - context.configuration().validate(); - //TODO take information from container to configure application - } + context.configuration().validate(); + saveApplicationState(); // make context available to application in case it is gcube-aware @@ -279,6 +275,7 @@ public class ApplicationManager { @Override public void contextInitialized(ServletContextEvent sce) { log.info("initilizing context {} ",context.name()); + context.events().fire(context.application().getContextPath(), ApplicationLifecycle.activation); log.info("webApp {} initialized ",context.name()); } diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 822d914..cfc6eb9 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -14,16 +14,17 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.ObjectInputStream; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.UUID; import javax.servlet.ServletContext; import org.gcube.common.events.Hub; import org.gcube.common.events.impl.DefaultHub; -import org.gcube.informationsystem.publisher.RegistryPublisherFactory; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; import org.gcube.smartgears.configuration.application.ApplicationExtensions; @@ -41,8 +42,15 @@ import org.gcube.smartgears.context.container.DefaultContainerContext; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.publishing.Publisher; +import org.gcube.smartgears.publishing.SmartgearsProfilePublisher; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.utils.Utils; +import org.reflections.Reflections; +import org.reflections.scanners.SubTypesScanner; +import org.reflections.scanners.TypeAnnotationsScanner; +import org.reflections.util.ClasspathHelper; +import org.reflections.util.ConfigurationBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -66,6 +74,8 @@ public class DefaultProvider implements Provider { this.configFile = configFile; } + List publishers; + protected DefaultProvider(){}; @@ -194,7 +204,7 @@ public class DefaultProvider implements Provider { ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - + //searching for smartegars related application handlers in the common classloader ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); @@ -204,7 +214,7 @@ public class DefaultProvider implements Provider { } ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader); - + return defaultHandlers; @@ -329,9 +339,38 @@ public class DefaultProvider implements Provider { } @Override - public ScopedPublisher publisher() { - return containerContext.configuration().mode()==Mode.online? RegistryPublisherFactory.scopedPublisher() - : new OfflinePublisher(); + public synchronized List publishers() { + if (this.publishers == null) { + //retrieve from root class loader + Collection urls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()); + urls.removeIf(url -> url.toString().endsWith(".so") || url.toString().endsWith(".zip") ); + + + ConfigurationBuilder reflectionConf = new ConfigurationBuilder().addUrls(urls).setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()); + + Reflections reflection = new Reflections(reflectionConf); + + Set> annotatedPublishers = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class); + List foundPublishers = new ArrayList(); + for (Class annotatedPublisher: annotatedPublishers) { + if (Publisher.class.isAssignableFrom(annotatedPublisher)) + try { + foundPublishers.add((Publisher)annotatedPublisher.newInstance()); + log.info("added class {} to publishers",annotatedPublisher); + } catch (Exception e) { + log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(),e); + } + else + log.warn("publisher class {} discarded, it doesn't implements Publisher class", annotatedPublisher.getCanonicalName()); + + } + this.publishers = foundPublishers; + + if (foundPublishers.isEmpty()) + log.warn("no publishers found in classloader"); + } + + return this.publishers; } diff --git a/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java b/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java deleted file mode 100644 index 4f1cc1d..0000000 --- a/src/main/java/org/gcube/smartgears/provider/OfflinePublisher.java +++ /dev/null @@ -1,56 +0,0 @@ -package org.gcube.smartgears.provider; - -import java.lang.reflect.Method; -import java.util.List; - -import org.gcube.common.resources.gcore.Resource; -import org.gcube.informationsystem.publisher.ScopedPublisher; -import org.gcube.informationsystem.publisher.exception.RegistryNotFoundException; -import org.gcube.smartgears.configuration.Mode; - -/** - * An implementation of {@link ScopedPublisher} that simulates remote publication. - *

- * Used for applications and or containers that operate in {@link Mode#offline}. - * - * @author Fabio Simeoni - * - */ -public class OfflinePublisher implements ScopedPublisher { - - @Override - public T update(T resource){ - // do nothing - return resource; - } - - @Override - public T create(T resource, List scopes) - throws RegistryNotFoundException { - // fragile! bypass restrictions reflectively and set new scope - for (String scope : scopes) - try { - Method m = resource.getClass().getSuperclass().getDeclaredMethod("addScope", String.class); - m.setAccessible(true); - m.invoke(resource, scope); - } catch (Exception e) { - throw new RuntimeException("could not simulate publication in scope " + scope, e); - } - return resource; - } - - @Override - public T remove(T resource, List scopes) - throws RegistryNotFoundException { - for (String scope : scopes) - try { - Method m = resource.getClass().getSuperclass().getDeclaredMethod("removeScope", String.class); - m.setAccessible(true); - m.invoke(resource, scope); - } catch (Exception e) { - throw new RuntimeException("could not simulate publication remove from scope " + scope, e); - } - return resource; - } - -} diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index 113d389..1f95b22 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -4,13 +4,13 @@ import java.util.List; import javax.servlet.ServletContext; -import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.handlers.container.ContainerHandler; +import org.gcube.smartgears.publishing.Publisher; import org.gcube.smartgears.security.AuthorizationProvider; /** @@ -46,7 +46,7 @@ public interface Provider { * Returns an implementation of the IS publisher for the container * @return the publisher implementation */ - ScopedPublisher publisher(); + List publishers(); //application-level dependencies diff --git a/src/main/java/org/gcube/smartgears/publishing/Publisher.java b/src/main/java/org/gcube/smartgears/publishing/Publisher.java index 6d30126..d5a5105 100644 --- a/src/main/java/org/gcube/smartgears/publishing/Publisher.java +++ b/src/main/java/org/gcube/smartgears/publishing/Publisher.java @@ -1,15 +1,17 @@ package org.gcube.smartgears.publishing; -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; +import java.util.Set; + +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.smartgears.context.container.ContainerContext; public interface Publisher { - boolean publishContainer(ContainerConfiguration container, String ... contexts); + boolean publishContainer(ContainerContext container, Set contexts); - boolean publishApplication(ApplicationConfiguration application, String ... contexts); + boolean publishApplication(ApplicationContext application, Set contexts); - boolean unpublishContainer(ContainerConfiguration container, String ... contexts); + boolean unpublishContainer(ContainerContext container, Set contexts); - boolean unpublishApplication(ApplicationConfiguration application, String ... contexts); + boolean unpublishApplication(ApplicationContext application, Set contexts); } diff --git a/src/main/java/org/gcube/smartgears/publishing/SmartgearsProfilePublisher.java b/src/main/java/org/gcube/smartgears/publishing/SmartgearsProfilePublisher.java new file mode 100644 index 0000000..5bd91f5 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/publishing/SmartgearsProfilePublisher.java @@ -0,0 +1,5 @@ +package org.gcube.smartgears.publishing; + +public @interface SmartgearsProfilePublisher { + +} diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index ef8e935..aae0ede 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -11,7 +11,7 @@ import org.gcube.common.keycloak.KeycloakClientFactory; import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; -import org.gcube.common.scope.impl.ScopeBean; +import org.gcube.common.security.ContextBean; import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.Secret; import org.gcube.smartgears.security.AuthorizationProvider; @@ -38,15 +38,11 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { public Set getContexts() { Set contexts = new HashSet(); try { - TokenResponse response; - if (this.endpoint == null) - response = client.queryOIDCToken(credentials.getClientID(), credentials.getSecret()); - else - response = client.queryOIDCToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret()); + TokenResponse response = client.queryOIDCToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret()); Map resourceAccess = ModelUtils.getAccessTokenFrom(response).getResourceAccess(); for (String context : resourceAccess.keySet()) { try { - ScopeBean scope = new ScopeBean(context.replaceAll("%2F", "/")); + ContextBean scope = new ContextBean(context.replaceAll("%2F", "/")); contexts.add(scope.toString()); LOG.info("found context {}",context); }catch (IllegalArgumentException e) { @@ -64,12 +60,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { @Override public Secret getSecretForContext(String context) { try { - TokenResponse response; - if (this.endpoint == null) - response = client.queryUMAToken(credentials.getClientID(), credentials.getSecret(), context, null); - else - response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); - + TokenResponse response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); return new AccessTokenSecret(response.getAccessToken()); } catch (Exception e) { diff --git a/src/test/java/utils/TestProvider.java b/src/test/java/utils/TestProvider.java index be3042e..7dd0014 100644 --- a/src/test/java/utils/TestProvider.java +++ b/src/test/java/utils/TestProvider.java @@ -4,7 +4,6 @@ import java.io.File; import javax.servlet.ServletContext; -import org.gcube.informationsystem.publisher.ScopedPublisher; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; @@ -23,11 +22,7 @@ public class TestProvider extends DefaultProvider { public ApplicationConfiguration configuration; public ApplicationHandlers handlers; public ApplicationExtensions extensions; - public ScopedPublisher publisher; - public void use(ScopedPublisher publisher) { - this.publisher=publisher; - } public void use(ApplicationConfiguration configuration) { this.configuration=configuration; @@ -50,11 +45,7 @@ public class TestProvider extends DefaultProvider { return conf ; } - @Override - public ScopedPublisher publisher() { - return publisher==null?super.publisher():publisher; - } - + @Override public ApplicationContext contextFor(ContainerContext container,ServletContext application) { return context = super.contextFor(container,application); diff --git a/src/test/resources/container.ini b/src/test/resources/container.ini index dd6a102..b0ec5b3 100644 --- a/src/test/resources/container.ini +++ b/src/test/resources/container.ini @@ -30,7 +30,7 @@ location = rome ; mandatory ; optional fields: provider factory (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory -endpoint = testEndpoint +endpoint = https://accounts.dev.d4science.org/auth/realms/d4science credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.clientID = testClient credentials.secret = testSecret From 80f5de688a8c957768bfbab1f38ceb5e65dbd3f9 Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 10 Jun 2022 18:25:19 +0200 Subject: [PATCH 21/49] allowed context retrieved on request --- .../container/ContainerConfiguration.java | 16 ---------------- .../application/request/RequestValidator.java | 9 ++++++--- .../smartgears/managers/ContainerManager.java | 3 --- .../persistence/PersistenceWriter.java | 2 ++ 4 files changed, 8 insertions(+), 22 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index a897a71..6744a73 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -3,12 +3,8 @@ package org.gcube.smartgears.configuration.container; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; - -import javax.xml.bind.annotation.XmlTransient; import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; @@ -46,9 +42,6 @@ public class ContainerConfiguration { @NotEmpty @NotNull private String accountingFallbackLocation; - - @XmlTransient - private Set allowedContext = new HashSet(); private List apps = new ArrayList(); @@ -234,15 +227,6 @@ public class ContainerConfiguration { return baseConfiguration.getPublicationFrequencyInSeconds(); } - - public Set allowedContexts() { - return allowedContext; - } - - public void allowedContexts(Set allowedContexts) { - this.allowedContext = allowedContexts; - } - /** * Validates this configuration * diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 09bd236..fb2339c 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -5,6 +5,8 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.app import static org.gcube.smartgears.handlers.application.request.RequestError.application_unavailable_error; import static org.gcube.smartgears.handlers.application.request.RequestError.invalid_request_error; +import java.util.Set; + import javax.xml.bind.annotation.XmlRootElement; import org.gcube.common.security.ContextBean; @@ -92,10 +94,11 @@ public class RequestValidator extends RequestHandler { ContextBean bean = new ContextBean(context); ContainerConfiguration conf = appContext.container().configuration(); - if (!conf.allowedContexts().contains(context) && + Set allowedContexts =conf.authorizationProvider().getContexts(); + if (!allowedContexts.contains(context) && !(conf.authorizeChildrenContext() && bean.is(Type.VRE) - && conf.allowedContexts().contains(bean.enclosingScope().toString()) ) ) { - log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),context,appContext.container().configuration().allowedContexts()); + && allowedContexts.contains(bean.enclosingScope().toString()) ) ) { + log.warn("rejecting call to {} in invalid context {}, allowed context are {}",appContext.name(),context,allowedContexts); invalid_request_error.fire(appContext.name()+" cannot be called in scope "+context); } } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index c2c2d54..8e8bac4 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -111,10 +111,7 @@ public class ContainerManager { log.error("no valid contexts found, moving the container to failed"); throw new RuntimeException("no valid contexts found, moving the container to failed"); } - - //context.configuration().startTokens().removeAll(tokensToRemove); - context.configuration().allowedContexts(foundContexts); } public void manage(ApplicationContext app) { diff --git a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java index 528b350..6bbb144 100644 --- a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java +++ b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java @@ -9,5 +9,7 @@ public interface PersistenceWriter { File writefile(String path); long getFreeSpace(); + + String getLocation(); } \ No newline at end of file From 6f999bcedcf9fa1a7802a8303169358440f2964e Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 15 Jun 2022 17:44:52 +0200 Subject: [PATCH 22/49] added caller information --- .../request/RequestAccounting.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index 3fad47f..c556472 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -28,7 +28,7 @@ public class RequestAccounting extends RequestHandler { private static ThreadLocal startCallThreadLocal = new ThreadLocal(); - + private static final String UNKNOWN = "Unknown"; @Override public String getName() { @@ -42,15 +42,14 @@ public class RequestAccounting extends RequestHandler { String context = getContext(appContext); - String calledMethod = e.request().getHeader(Constants.called_method_header); - if (calledMethod==null){ - calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); - if (calledMethod.isEmpty()) - calledMethod = "/"; - calledMethod= e.request().getMethod()+" "+calledMethod; - } + String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); + if (calledMethod.isEmpty()) + calledMethod = "/"; + calledMethod= e.request().getMethod()+" "+calledMethod; + InnerMethodName.instance.set(calledMethod); - String caller = "Unknown"; + String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): + UNKNOWN; startCallThreadLocal.set(System.currentTimeMillis()); log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", @@ -67,8 +66,9 @@ public class RequestAccounting extends RequestHandler { String context = getContext(appContext); - String caller = "Unknown"; - String callerQualifier = "UNKNOWN"; + String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): + UNKNOWN; + String callerQualifier = UNKNOWN; //retieves caller Ip when there is a proxy String callerIp = e.request().getHeader("x-forwarded-for"); if(callerIp==null) @@ -77,7 +77,7 @@ public class RequestAccounting extends RequestHandler { boolean success = e.response().getStatus()<400; if (appContext.container().configuration().mode()!=Mode.offline) - generateAccounting(caller,callerQualifier,callerIp==null?"UNKNOWN":callerIp , success, context, appContext); + generateAccounting(caller,callerQualifier,callerIp==null?UNKNOWN:callerIp , success, context, appContext); long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); From 08781a5f3a83ce987e76ae763a3901b2728d3732 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 22 Jun 2022 18:50:54 +0200 Subject: [PATCH 23/49] Profile and App events updated --- .../application/ApplicationConfiguration.java | 4 --- .../BridgedApplicationConfiguration.java | 12 --------- .../DefaultApplicationConfiguration.java | 25 ++++++------------- .../ContainerConfigurationBinder.java | 5 ++-- .../lifecycle/ApplicationProfileManager.java | 1 - .../lifecycle/ContainerProfileManager.java | 1 - .../managers/ApplicationManager.java | 2 +- .../AuthorizationProviderFactory.java | 3 +-- .../DefaultAuthorizationProvider.java | 5 ++++ .../DefaultAuthorizationProviderFactory.java | 23 +++++++++++++++-- src/test/resources/container.ini | 6 ++--- 11 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index 4b9bbaf..50bbaff 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -2,7 +2,6 @@ package org.gcube.smartgears.configuration.application; import java.util.Set; -import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.persistence.PersistenceWriter; /** @@ -83,9 +82,6 @@ public interface ApplicationConfiguration { */ ApplicationConfiguration description(String description); - ProxyAddress proxyAddress(); - - ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress); /** diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java index 7db8345..9bea447 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java @@ -2,7 +2,6 @@ package org.gcube.smartgears.configuration.application; import java.util.Set; -import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.persistence.PersistenceWriter; import org.slf4j.Logger; @@ -74,10 +73,6 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration public String description() { return application.description(); } - - public ProxyAddress proxyAddress() { - return application.proxyAddress(); - } public ApplicationConfiguration description(String description) { return application.description(description); @@ -129,11 +124,4 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration return application.includes(includes); } - @Override - public ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress) { - return application.proxyAddress(proxyaddress); - } - - - } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java index d211dcf..e091b3b 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java @@ -7,6 +7,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; +import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlRootElement; @@ -32,7 +33,10 @@ import org.gcube.smartgears.persistence.PersistenceWriter; public class DefaultApplicationConfiguration implements ApplicationConfiguration { String context; - + + @XmlAttribute(name = "proxied") + private boolean proxied = true; + @XmlElement(name="name" , required=true) @NotNull String name; @@ -47,10 +51,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElement(name="description") String description=""; - - @IsValid - ProxyAddress proxyAddress; - + @XmlElementRef Set excludes= new LinkedHashSet(); @@ -88,11 +89,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration this.context=context; return this; } - - public ProxyAddress proxyAddress() { - return proxyAddress; - } - + @Override public ApplicationConfiguration excludes(Exclude ... excludes) { this.excludes=new HashSet(Arrays.asList(excludes)); @@ -148,7 +145,7 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @Override public boolean proxied() { - return proxyAddress!=null; + return proxied; } @Override @@ -161,12 +158,6 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration this.persistenceManager=manager; return this; } - - @Override - public ApplicationConfiguration proxyAddress(ProxyAddress proxyaddress) { - this.proxyAddress = proxyaddress; - return this; - } @Override public void validate() { diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 7f34680..1cf98ab 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -114,7 +114,6 @@ public class ContainerConfigurationBinder { if (authorizationSection != null) { String provider = authorizationSection.get("factory"); - String authEndpoint = authorizationSection.get("endpoint"); AuthorizationProviderFactory authProviderFactory; if (provider!=null) { try { @@ -126,6 +125,8 @@ public class ContainerConfigurationBinder { } else authProviderFactory = new DefaultAuthorizationProviderFactory(); + authorizationSection.to(authProviderFactory, "factory."); + String type = authorizationSection.get("credentials.class"); if (type ==null) @@ -139,7 +140,7 @@ public class ContainerConfigurationBinder { } authorizationSection.to(credentials, "credentials."); - AuthorizationProvider authProvider = authProviderFactory.connect(credentials, authEndpoint); + AuthorizationProvider authProvider = authProviderFactory.connect(credentials); conf.setAuthorizationProvider(authProvider); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 57477ea..6c28f86 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -66,7 +66,6 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { activated(); - schedulePeriodicUpdates(); // note we don't fire profile events, but wait for the final startup // outcome which // will result in a state change. only then we publish and store the diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index c29388e..b414098 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -66,7 +66,6 @@ public class ContainerProfileManager extends ContainerHandler { activated(); - schedulePeriodicUpdates(); // note we don't fire profile events, but wait for the final startup // outcome which // will result in a state change. only then we publish and store the diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index 579301f..4f3bfe1 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -276,7 +276,7 @@ public class ApplicationManager { public void contextInitialized(ServletContextEvent sce) { log.info("initilizing context {} ",context.name()); - context.events().fire(context.application().getContextPath(), ApplicationLifecycle.activation); + context.events().fire(context, ApplicationLifecycle.activation); log.info("webApp {} initialized ",context.name()); } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java index 6892b20..c18bcd7 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java @@ -2,7 +2,6 @@ package org.gcube.smartgears.security; public interface AuthorizationProviderFactory { - T connect(Credentials credentials, String endpoint); - + T connect(Credentials credentials); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index aae0ede..65363d5 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -70,4 +70,9 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { } + @Deprecated + //TODO: remove when whnManager will be removed + public SimpleCredentials getCredentials() { + return credentials; + } } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java index 9fac9e0..ba7fddf 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java @@ -1,17 +1,36 @@ package org.gcube.smartgears.security.defaults; +import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.smartgears.security.AuthorizationProviderFactory; import org.gcube.smartgears.security.Credentials; import org.gcube.smartgears.security.SimpleCredentials; public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory{ + @NotEmpty + private String endpoint; + @Override - public DefaultAuthorizationProvider connect(Credentials credentials, String enpoint) { + public DefaultAuthorizationProvider connect(Credentials credentials) { if (!SimpleCredentials.class.isInstance(credentials)) throw new IllegalArgumentException("invalid credential type passed"); - return new DefaultAuthorizationProvider((SimpleCredentials)credentials, enpoint); + if (this.endpoint == null || this.endpoint.isEmpty()) + throw new IllegalArgumentException("invalid enpoint passed"); + return new DefaultAuthorizationProvider((SimpleCredentials)credentials, this.endpoint); } + @Override + public String toString() { + return "DefaultAuthorizationProviderFactory [endpoint=" + endpoint + "]"; + } + + public String getEndpoint() { + return endpoint; + } + + public void setEndpoint(String endpoint) { + this.endpoint = endpoint; + } + } diff --git a/src/test/resources/container.ini b/src/test/resources/container.ini index b0ec5b3..8319c5c 100644 --- a/src/test/resources/container.ini +++ b/src/test/resources/container.ini @@ -11,12 +11,11 @@ publicationFrequencyInSeconds = 60 [properties] ; not mandatory -SmartGearsDistribution = 0.0.1 +SmartGearsDistribution = 1.0.0 SmartGearsDistributionBundle = UnBundled [site] ; mandatory -; optional fields: latitude, logitude country = it location = rome @@ -26,11 +25,12 @@ location = rome ;hostname = proxy ;port = 80 + [authorization] ; mandatory ; optional fields: provider factory (=org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory) factory = org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory -endpoint = https://accounts.dev.d4science.org/auth/realms/d4science +factory.endpoint = https://accounts.dev.d4science.org/auth/realms/d4science/protocol/openid-connect/token credentials.class = org.gcube.smartgears.security.SimpleCredentials credentials.clientID = testClient credentials.secret = testSecret From 710e8ef242b37f99b1ec9135abb23518abb1c7aa Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 24 Jun 2022 15:45:43 +0200 Subject: [PATCH 24/49] Proxy management improved --- .../application/ApplicationConfiguration.java | 7 ++++- .../BridgedApplicationConfiguration.java | 30 ++++++++++++++++--- .../DefaultApplicationConfiguration.java | 26 ++++++++++++---- .../lifecycle/ApplicationProfileManager.java | 6 ++-- .../persistence/LocalPersistence.java | 9 +++++- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index 50bbaff..6b2a9ec 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -2,6 +2,7 @@ package org.gcube.smartgears.configuration.application; import java.util.Set; +import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.persistence.PersistenceWriter; /** @@ -19,7 +20,11 @@ public interface ApplicationConfiguration { */ String context(); - boolean proxied(); + boolean proxable(); + + ProxyAddress proxyAddress(); + + ApplicationConfiguration proxyAddress(ProxyAddress proxy); /** * Sets the context path of the application diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java index 9bea447..8028765 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java @@ -1,8 +1,11 @@ package org.gcube.smartgears.configuration.application; +import java.io.File; import java.util.Set; +import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.container.ContainerConfiguration; +import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -25,11 +28,20 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration if (application.persistence()==null) { - application.persistence(container.persistence()); + String location = container.persistence().getLocation()+"/"+application.name(); + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + + application.persistence(new LocalPersistence(location)); + + log.trace("setting persistence location for {} @ {}",application.name(), dir.getAbsolutePath()); - log.trace("setting persistence location for {} the same as the container persistence",application.name()); } + if (application.proxable() && container.proxy()!=null) + application.proxyAddress(container.proxy()); + } public ApplicationConfiguration inner() { @@ -110,8 +122,8 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration @Override - public boolean proxied() { - return application.proxied(); + public boolean proxable() { + return application.proxable(); } @Override @@ -124,4 +136,14 @@ public class BridgedApplicationConfiguration implements ApplicationConfiguration return application.includes(includes); } + @Override + public ProxyAddress proxyAddress() { + return application.proxyAddress(); + } + + @Override + public ApplicationConfiguration proxyAddress(ProxyAddress proxy) { + return proxyAddress(proxy); + } + } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java index e091b3b..94248e6 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java @@ -18,6 +18,7 @@ import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotNull; import org.gcube.smartgears.configuration.ProxyAddress; +import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; /** @@ -34,8 +35,8 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration String context; - @XmlAttribute(name = "proxied") - private boolean proxied = true; + @XmlAttribute(name = "proxable") + private boolean proxable = true; @XmlElement(name="name" , required=true) @NotNull @@ -58,9 +59,13 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration @XmlElementRef Set includes= new LinkedHashSet(); + @XmlElementRef(type=LocalPersistence.class) @NotNull @IsValid private PersistenceWriter persistenceManager; + @IsValid + ProxyAddress proxyAddress; + @Override public Set excludes() { return excludes; @@ -144,10 +149,21 @@ public class DefaultApplicationConfiguration implements ApplicationConfiguration } @Override - public boolean proxied() { - return proxied; + public boolean proxable() { + return proxable; } - + + public ProxyAddress proxyAddress() { + return proxyAddress; + } + + + public ApplicationConfiguration proxyAddress(ProxyAddress proxyAddress) { + this.proxyAddress = proxyAddress; + return this; + } + + @Override public PersistenceWriter persistence() { return persistenceManager; diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 6c28f86..742631b 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -207,8 +207,10 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { context.events().fire(context,changed); } }; - - periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, Constants.application_republish_frequency_in_minutes, Constants.application_republish_frequency_in_minutes , TimeUnit.MINUTES); + + periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, + Constants.application_republish_frequency_in_minutes, + Constants.application_republish_frequency_in_minutes , TimeUnit.MINUTES); } diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java index e298a53..49a9026 100644 --- a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java +++ b/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java @@ -8,12 +8,19 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAttribute; +import javax.xml.bind.annotation.XmlRootElement; + import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; +@XmlRootElement(name="persistence") +@XmlAccessorType(XmlAccessType.FIELD) public class LocalPersistence implements PersistenceWriter { - @NotNull @NotEmpty + @XmlAttribute(name="location") @NotNull @NotEmpty private String location; protected LocalPersistence() {} From 58bb6a28e4a6562bf3630d2f95a7de830b31bdce Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Tue, 28 Jun 2022 13:28:16 +0200 Subject: [PATCH 25/49] changed publisher interface --- .../lifecycle/ApplicationProfileManager.java | 7 +++---- .../container/lifecycle/ContainerProfileManager.java | 7 +++---- .../org/gcube/smartgears/publishing/Publisher.java | 12 ++++++++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 742631b..ec0c9a2 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -120,8 +120,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { //(we may well have failed there) for (Publisher publisher: publishers) try { - publisher.publishApplication(context, - context.container().configuration().authorizationProvider().getContexts()); + publisher.update(context); }catch (Exception e) { log.error("cannot publish {} with publisher type {} (see details)",context.name(), publisher.getClass().getCanonicalName(), e); @@ -140,7 +139,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { for (Publisher publisher: publishers) try { log.debug("publishing application in context {}", scope); - publisher.publishApplication(context, + publisher.create(context, Collections.singleton(scope)); }catch (Exception e) { @@ -161,7 +160,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { for (Publisher publisher: publishers) try { log.debug("unpublishing application from scope {}", scope); - publisher.unpublishApplication(context, + publisher.remove(context, Collections.singleton(scope)); }catch (Exception e) { diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index b414098..a15ba64 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -104,8 +104,7 @@ public class ContainerProfileManager extends ContainerHandler { //(we may well have failed there) for (Publisher publisher: publishers) try { - publisher.publishContainer(context, - context.configuration().authorizationProvider().getContexts()); + publisher.update(context); }catch (Exception e) { log.error("cannot publish containar with publisher type {} (see details)", publisher.getClass().getCanonicalName(), e); @@ -123,7 +122,7 @@ public class ContainerProfileManager extends ContainerHandler { for (Publisher publisher: publishers) try { log.trace("publishing container within new scope"); - publisher.publishContainer(context, + publisher.create(context, Collections.singleton(scope)); }catch (Exception e) { @@ -144,7 +143,7 @@ public class ContainerProfileManager extends ContainerHandler { for (Publisher publisher: publishers) try { log.trace("unpublishing container from context {}", scope); - publisher.unpublishContainer(context, + publisher.remove(context, Collections.singleton(scope)); }catch (Exception e) { diff --git a/src/main/java/org/gcube/smartgears/publishing/Publisher.java b/src/main/java/org/gcube/smartgears/publishing/Publisher.java index d5a5105..8c451f8 100644 --- a/src/main/java/org/gcube/smartgears/publishing/Publisher.java +++ b/src/main/java/org/gcube/smartgears/publishing/Publisher.java @@ -7,11 +7,15 @@ import org.gcube.smartgears.context.container.ContainerContext; public interface Publisher { - boolean publishContainer(ContainerContext container, Set contexts); + boolean create(ContainerContext container, Set contexts); - boolean publishApplication(ApplicationContext application, Set contexts); + boolean create(ApplicationContext application, Set contexts); - boolean unpublishContainer(ContainerContext container, Set contexts); + boolean update(ApplicationContext application); - boolean unpublishApplication(ApplicationContext application, Set contexts); + boolean update(ContainerContext container); + + boolean remove(ApplicationContext application, Set contexts); + + boolean remove(ContainerContext application, Set contexts); } From 1b79f8e813276afefcfdec986e351599bc9115f5 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Tue, 28 Jun 2022 16:18:02 +0200 Subject: [PATCH 26/49] updated publisher interface --- .../smartgears/publishing/Publisher.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/main/java/org/gcube/smartgears/publishing/Publisher.java b/src/main/java/org/gcube/smartgears/publishing/Publisher.java index 8c451f8..28a223c 100644 --- a/src/main/java/org/gcube/smartgears/publishing/Publisher.java +++ b/src/main/java/org/gcube/smartgears/publishing/Publisher.java @@ -7,15 +7,57 @@ import org.gcube.smartgears.context.container.ContainerContext; public interface Publisher { + /** + * creates the container resource in the context + * + * @param container + * @param contexts the new contexts where the resource must be created + * @return + */ boolean create(ContainerContext container, Set contexts); + /** + * creates the application resource in the contexts + * + * @param application + * @param contexts the new contexts where the resource must be created + * @return + */ boolean create(ApplicationContext application, Set contexts); + + /** + * updates the application resource + * + * @param application + * @return + */ boolean update(ApplicationContext application); + /** + * updates the container resource + * + * @param container + * @return + */ boolean update(ContainerContext container); + + /** + * removes the application resource from the contexts + * + * @param application + * @param contexts the contexts from where the resource must be removed + * @return + */ boolean remove(ApplicationContext application, Set contexts); + + /** + * removes the container resource from the contexts + * @param application + * @param contexts the contexts from where the resource must be removed + * @return + */ boolean remove(ContainerContext application, Set contexts); } From 7e00459e9a2996682b6c91129e12fa80878ba1f5 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Thu, 30 Jun 2022 12:33:55 +0200 Subject: [PATCH 27/49] logs added --- .../lifecycle/ApplicationProfileManager.java | 70 +++++++++++-------- .../lifecycle/ContainerProfileManager.java | 57 +++++++++------ 2 files changed, 73 insertions(+), 54 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index ec0c9a2..2228dc7 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -18,6 +18,7 @@ import org.gcube.common.events.Observes; import org.gcube.common.events.Observes.Kind; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.context.Property; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; @@ -46,8 +47,6 @@ import org.slf4j.LoggerFactory; * * * @author Fabio Simeoni - * @see ProfileBuilder - * @see ProfilePublisherImpl */ public class ApplicationProfileManager extends ApplicationLifecycleHandler { @@ -55,7 +54,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { private ApplicationContext context; private ScheduledFuture periodicUpdates; - + private static final String PUBLISHED_PROP = "published"; private List publishers = ProviderFactory.provider().publishers(); @@ -80,12 +79,12 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { private void activated(){ - + publishers = context.container().configuration().mode()!=Mode.offline? ProviderFactory.provider().publishers(): Collections.emptyList(); - registerObservers(); - schedulePeriodicUpdates(); + registerObservers(); + schedulePeriodicUpdates(); } // helpers @@ -118,19 +117,28 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { //if we've failed before first publication do not try to publish //(we may well have failed there) - for (Publisher publisher: publishers) - try { - publisher.update(context); - }catch (Exception e) { - - log.error("cannot publish {} with publisher type {} (see details)",context.name(), publisher.getClass().getCanonicalName(), e); - - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); + if (context.properties().contains(PUBLISHED_PROP)) { + log.info("publishing application for the first time"); + context.properties().add(new Property(PUBLISHED_PROP, true)); + if (context.lifecycle().state() != ApplicationState.failed) { + publishers.forEach(p -> { + try { + p.create(context, + context.container().configuration().authorizationProvider().getContexts()); + }catch (Exception e) { + log.error("cannot publish {} for first time with publisher type {} (see details)",context.name(), p.getClass().getCanonicalName(), e); + } + }); } + } + else + publishers.forEach(p -> { + try { + p.update(context); + }catch (Exception e) { + log.error("cannot publish {} with publisher type {} (see details)",context.name(), p.getClass().getCanonicalName(), e); + } + }); } @@ -158,20 +166,20 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { @Observes(value = removeFromContext) void removeFrom(String scope) { for (Publisher publisher: publishers) - try { - log.debug("unpublishing application from scope {}", scope); - publisher.remove(context, - Collections.singleton(scope)); - }catch (Exception e) { + try { + log.debug("unpublishing application from scope {}", scope); + publisher.remove(context, + Collections.singleton(scope)); + }catch (Exception e) { - log.error("cannot remove scope {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); + log.error("cannot remove scope {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); - } + // since we've failed no published event is fired and profile + // will not be stored. + // we do it manually to ensure we leave some local trace of the + // changed profile. + //TODO: CHECK --- store(profile); + } } }); @@ -206,7 +214,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { context.events().fire(context,changed); } }; - + periodicUpdates = Utils.scheduledServicePool.scheduleAtFixedRate(updateTask, Constants.application_republish_frequency_in_minutes, Constants.application_republish_frequency_in_minutes , TimeUnit.MINUTES); diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index a15ba64..3f16126 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -20,10 +20,12 @@ import java.util.concurrent.ScheduledFuture; import org.gcube.common.events.Observes; import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.context.Property; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.lifecycle.container.ContainerState; import org.gcube.smartgears.provider.ProviderFactory; import org.gcube.smartgears.publishing.Publisher; import org.gcube.smartgears.utils.Utils; @@ -55,7 +57,7 @@ public class ContainerProfileManager extends ContainerHandler { private ContainerContext context; private ScheduledFuture periodicUpdates; - + private static final String PUBLISHED_PROP = "published"; private List publishers; @@ -83,40 +85,49 @@ public class ContainerProfileManager extends ContainerHandler { publishers = context.configuration().mode()!=Mode.offline? ProviderFactory.provider().publishers(): Collections.emptyList(); - registerObservers(); - schedulePeriodicUpdates(); + registerObservers(); + schedulePeriodicUpdates(); } - + private void registerObservers() { context.events().subscribe(new Object() { @Observes({ activation, part_activation, shutdown, stop, failure }) void onChanged(ContainerLifecycle lc) { - + // since we do not know the observers, they will deal with failures and their consequences // any that comes back will be logged in this event thread context.events().fire(context, changed); } - + @Observes(value = changed, kind = critical) void publishAfterChange(ContainerContext context) { log.info("Publish after profile Change event called"); //if we've failed before first publication do not try to publish //(we may well have failed there) - for (Publisher publisher: publishers) - try { - publisher.update(context); - }catch (Exception e) { - - log.error("cannot publish containar with publisher type {} (see details)", publisher.getClass().getCanonicalName(), e); - - // since we've failed no published event is fired and profile - // will not be stored. - // we do it manually to ensure we leave some local trace of the - // changed profile. - //TODO: CHECK --- store(profile); + if (context.properties().contains(PUBLISHED_PROP)) { + context.properties().add(new Property(PUBLISHED_PROP, true)); + log.info("publishing container for the first time"); + if (context.lifecycle().state() != ContainerState.failed) { + publishers.forEach(p -> { + try { + p.create(context, + context.configuration().authorizationProvider().getContexts()); + }catch (Exception e) { + log.error("cannot publish container for first time with publisher type {} (see details)", p.getClass().getCanonicalName(), e); + } + }); } + } + else + publishers.forEach(p -> { + try { + p.update(context); + }catch (Exception e) { + log.error("cannot publish container with publisher type {} (see details)", p.getClass().getCanonicalName(), e); + } + }); } - + @Observes(value = addToContext) void addTo(String scope) { for (Publisher publisher: publishers) @@ -135,9 +146,9 @@ public class ContainerProfileManager extends ContainerHandler { // changed profile. //TODO: CHECK --- store(profile); } - + } - + @Observes(value = removeFromContext) void removeFrom(String scope) { for (Publisher publisher: publishers) @@ -159,8 +170,8 @@ public class ContainerProfileManager extends ContainerHandler { } }); } - - + + private void schedulePeriodicUpdates() { // register to cancel updates context.events().subscribe( From b9e2298ca91543cc4274afb667558d48b8d85ea2 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 4 Jul 2022 16:31:15 +0200 Subject: [PATCH 28/49] fixed bug on first publishing --- .../application/lifecycle/ApplicationProfileManager.java | 2 +- .../handlers/container/lifecycle/ContainerProfileManager.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 2228dc7..683a4a9 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -117,7 +117,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { //if we've failed before first publication do not try to publish //(we may well have failed there) - if (context.properties().contains(PUBLISHED_PROP)) { + if (!context.properties().contains(PUBLISHED_PROP)) { log.info("publishing application for the first time"); context.properties().add(new Property(PUBLISHED_PROP, true)); if (context.lifecycle().state() != ApplicationState.failed) { diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index 3f16126..c0eeb4d 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -104,7 +104,7 @@ public class ContainerProfileManager extends ContainerHandler { log.info("Publish after profile Change event called"); //if we've failed before first publication do not try to publish //(we may well have failed there) - if (context.properties().contains(PUBLISHED_PROP)) { + if (!context.properties().contains(PUBLISHED_PROP)) { context.properties().add(new Property(PUBLISHED_PROP, true)); log.info("publishing container for the first time"); if (context.lifecycle().state() != ContainerState.failed) { @@ -126,6 +126,7 @@ public class ContainerProfileManager extends ContainerHandler { log.error("cannot publish container with publisher type {} (see details)", p.getClass().getCanonicalName(), e); } }); + } @Observes(value = addToContext) From e5c0b8a23d55ac81854f90f646706c3bd4e540b5 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 6 Jul 2022 09:55:42 +0200 Subject: [PATCH 29/49] latitude and longitude removed --- .../configuration/container/Site.java | 34 ------------------- 1 file changed, 34 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/configuration/container/Site.java b/src/main/java/org/gcube/smartgears/configuration/container/Site.java index da6aec1..e81ce0b 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/Site.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/Site.java @@ -16,10 +16,6 @@ public class Site { @NotNull String location; - String latitude; - - String longitude; - public String getCountry() { return country; } @@ -36,30 +32,12 @@ public class Site { this.location = location; } - public String getLatitude() { - return latitude; - } - - public void setLatitude(String latitude) { - this.latitude = latitude; - } - - public String getLongitude() { - return longitude; - } - - public void setLongitude(String longitude) { - this.longitude = longitude; - } - @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((country == null) ? 0 : country.hashCode()); - result = prime * result + ((latitude == null) ? 0 : latitude.hashCode()); result = prime * result + ((location == null) ? 0 : location.hashCode()); - result = prime * result + ((longitude == null) ? 0 : longitude.hashCode()); return result; } @@ -77,24 +55,12 @@ public class Site { return false; } else if (!country.equals(other.country)) return false; - if (latitude == null) { - if (other.latitude != null) - return false; - } else if (!latitude.equals(other.latitude)) - return false; if (location == null) { if (other.location != null) return false; } else if (!location.equals(other.location)) return false; - if (longitude == null) { - if (other.longitude != null) - return false; - } else if (!longitude.equals(other.longitude)) - return false; return true; } - - } \ No newline at end of file From 4b75535a9d31c03f8998b19dc5506a58e7818697 Mon Sep 17 00:00:00 2001 From: lucio Date: Thu, 14 Jul 2022 11:56:32 +0200 Subject: [PATCH 30/49] added logs --- .../lifecycle/ApplicationProfileManager.java | 7 +++++++ .../lifecycle/ContainerProfileManager.java | 4 +++- .../smartgears/managers/ContainerManager.java | 14 +++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 683a4a9..5528d18 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -141,9 +141,14 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { }); } + }); + + //registering ContextObserver in container HUB + context.container().events().subscribe(new Object() { @Observes(value = addToContext) void addTo(String scope) { + log.info("add_to_context event arrived in app {}", context.name()); for (Publisher publisher: publishers) try { log.debug("publishing application in context {}", scope); @@ -165,6 +170,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { @Observes(value = removeFromContext) void removeFrom(String scope) { + log.info("remove_from_context event arrived in app {}", context.name()); for (Publisher publisher: publishers) try { log.debug("unpublishing application from scope {}", scope); @@ -183,6 +189,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { } }); + } private void schedulePeriodicUpdates() { diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index c0eeb4d..80adbd9 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -131,6 +131,7 @@ public class ContainerProfileManager extends ContainerHandler { @Observes(value = addToContext) void addTo(String scope) { + log.info("add_to_context event arrived in container"); for (Publisher publisher: publishers) try { log.trace("publishing container within new scope"); @@ -152,6 +153,7 @@ public class ContainerProfileManager extends ContainerHandler { @Observes(value = removeFromContext) void removeFrom(String scope) { + log.info("remove_from_context event arrived in container"); for (Publisher publisher: publishers) try { log.trace("unpublishing container from context {}", scope); @@ -160,7 +162,7 @@ public class ContainerProfileManager extends ContainerHandler { }catch (Exception e) { - log.error("cannot add container to {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); + log.error("cannot remove container from {} with publisher type {} (see details)",scope, publisher.getClass().getCanonicalName(), e); // since we've failed no published event is fired and profile // will not be stored. diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 8e8bac4..4dc0bb3 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -18,6 +18,7 @@ import org.gcube.common.events.Observes.Kind; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.handlers.ProfileEvents; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent; import org.gcube.smartgears.handlers.container.ContainerPipeline; @@ -115,9 +116,7 @@ public class ContainerManager { } public void manage(ApplicationContext app) { - app.events().subscribe(this); - } @Observes(value={ApplicationLifecycle.failure,ApplicationLifecycle.stop},kind=Kind.critical) @@ -126,14 +125,15 @@ public class ContainerManager { } @Observes(value=ContextEvents.ADD_CONTEXT_TO_CONTAINER,kind=Kind.critical) - void addContext(String context) { - log.trace("adding context {} to container", context); - + void addContext(String scope) { + log.info("adding context {} event send", context); + context.events().fire(scope, ProfileEvents.addToContext); } @Observes(value=ContextEvents.REMOVE_CONTEXT_FROM_CONTAINER,kind=Kind.critical) - void removeContext(String context) { - log.trace("removing context {} from container", context); + void removeContext(String scope) { + log.info("removing context {} event send", context); + context.events().fire(scope, ProfileEvents.removeFromContext); } /** From 2fe7d3d4bc1cfd342cae91c32d4a2c3628e35a6b Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 20 Jul 2022 17:31:20 +0200 Subject: [PATCH 31/49] InnerMethodName used for accounting --- .../request/RequestAccounting.java | 31 +++++++++++-------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index c556472..f7ec851 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -41,13 +41,16 @@ public class RequestAccounting extends RequestHandler { String context = getContext(appContext); - - String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); - if (calledMethod.isEmpty()) - calledMethod = "/"; - calledMethod= e.request().getMethod()+" "+calledMethod; - - InnerMethodName.instance.set(calledMethod); + + if (InnerMethodName.instance.get()==null) { + String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); + if (calledMethod.isEmpty()) + calledMethod = "/"; + calledMethod= e.request().getMethod()+" "+calledMethod; + + InnerMethodName.instance.set(calledMethod); + } + String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): UNKNOWN; startCallThreadLocal.set(System.currentTimeMillis()); @@ -63,7 +66,7 @@ public class RequestAccounting extends RequestHandler { ApplicationContext appContext = e.context(); try { - + String context = getContext(appContext); String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): @@ -78,9 +81,9 @@ public class RequestAccounting extends RequestHandler { if (appContext.container().configuration().mode()!=Mode.offline) generateAccounting(caller,callerQualifier,callerIp==null?UNKNOWN:callerIp , success, context, appContext); - + long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); - + Metrics.globalRegistry.timer("http.requests", "response",Integer.toString(e.response().getStatus()) , "context", context, "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, "caller-username", caller, "service-class", appContext.configuration().serviceClass(), "service-name", appContext.configuration().name(), @@ -89,12 +92,14 @@ public class RequestAccounting extends RequestHandler { log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), caller, callerIp, context, success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); - startCallThreadLocal.remove(); - InnerMethodName.instance.reset(); + }catch (Exception e1) { log.error("error on accounting",e); throw e1; + } finally { + startCallThreadLocal.remove(); + InnerMethodName.instance.reset(); } } @@ -130,7 +135,7 @@ public class RequestAccounting extends RequestHandler { context = SecretManagerProvider.instance.get().getContext(); return context; } - + @Override public String toString() { return getName(); From 08838cb6d64de782505f3bbb7141ddef5f2d1cf0 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 25 Jul 2022 11:00:44 +0200 Subject: [PATCH 32/49] removed vos from frontpage --- .../resource/FrontPageResource.java | 31 +------------------ .../request/RequestAccounting.java | 4 --- .../application/request/RequestValidator.java | 5 +-- src/main/resources/META-INF/frontpage.html | 2 +- 4 files changed, 3 insertions(+), 39 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index 2e3101c..6fa5b37 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -91,37 +91,8 @@ public class FrontPageResource extends ApiResource { values.put("version", context().configuration().version()); String infrastructure = context().container().configuration().infrastructure(); - StringBuilder voValue = new StringBuilder(); - - Set vos = new HashSet(); - - //pre-process - for (String scope : context().container().configuration().authorizationProvider().getContexts()) { - ContextBean bean = new ContextBean(scope); - switch (bean.type()) { - case INFRASTRUCTURE: - infrastructure = bean.name(); - break; - case VO: - vos.add(bean.name()); - break; - case VRE: - vos.add(bean.enclosingScope().name()); - infrastructure=bean.enclosingScope().enclosingScope().name(); - } - } - - //build vo value - int i = 0; - int max = vos.size()-1; - for (String vo : vos) { - String voPrefix = i == 0 ? "" : (i==max?" and ":", "); - voValue.append(voPrefix+"" + vo + ""); - i++; - } - + values.put("infra", infrastructure); - values.put("vos", voValue.toString()); values.put("status", context().lifecycle().state().toString()); diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index f7ec851..a815151 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -2,8 +2,6 @@ package org.gcube.smartgears.handlers.application.request; import java.util.concurrent.TimeUnit; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; @@ -21,7 +19,6 @@ import org.slf4j.LoggerFactory; import io.micrometer.core.instrument.Metrics; -@XmlRootElement(name = Constants.request_accounting) public class RequestAccounting extends RequestHandler { private static Logger log = LoggerFactory.getLogger(RequestAccounting.class); @@ -47,7 +44,6 @@ public class RequestAccounting extends RequestHandler { if (calledMethod.isEmpty()) calledMethod = "/"; calledMethod= e.request().getMethod()+" "+calledMethod; - InnerMethodName.instance.set(calledMethod); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index fb2339c..e8df27a 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -7,8 +7,6 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.inv import java.util.Set; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.security.ContextBean; import org.gcube.common.security.ContextBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; @@ -25,7 +23,6 @@ import org.gcube.smartgears.handlers.application.ResponseEvent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -@XmlRootElement(name = Constants.request_validation) public class RequestValidator extends RequestHandler { private static Logger log = LoggerFactory.getLogger(RequestValidator.class); @@ -119,7 +116,7 @@ public class RequestValidator extends RequestHandler { } private void validatePolicy(RequestEvent call){ - //TODO: must be re-think + //TODO: must be rethought } private Secret getSecret(RequestEvent call){ diff --git a/src/main/resources/META-INF/frontpage.html b/src/main/resources/META-INF/frontpage.html index 2b587fb..70eaf93 100644 --- a/src/main/resources/META-INF/frontpage.html +++ b/src/main/resources/META-INF/frontpage.html @@ -104,7 +104,7 @@

Welcome to ${name},

-

a resource of the ${infra} infrastructure shared in ${vos} VOs.

+

a resource of the ${infra} infrastructure

The resource is ${status}.

From b73a2963e5fbdbf7e531020b3f17a2478ca36752 Mon Sep 17 00:00:00 2001 From: lucio Date: Tue, 26 Jul 2022 15:46:43 +0200 Subject: [PATCH 33/49] Credentials moved to security library --- .../container/ContainerConfigurationBinder.java | 2 +- .../smartgears/security/AuthorizationProviderFactory.java | 2 ++ src/main/java/org/gcube/smartgears/security/Credentials.java | 5 ----- .../org/gcube/smartgears/security/SimpleCredentials.java | 1 + .../defaults/DefaultAuthorizationProviderFactory.java | 2 +- 5 files changed, 5 insertions(+), 7 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/security/Credentials.java diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 1cf98ab..95cc640 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -8,6 +8,7 @@ import java.util.List; import java.util.Map.Entry; import java.util.stream.Collectors; +import org.gcube.common.security.credentials.Credentials; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; @@ -16,7 +17,6 @@ import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.AuthorizationProviderFactory; -import org.gcube.smartgears.security.Credentials; import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory; import org.gcube.smartgears.utils.Utils; import org.ini4j.Ini; diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java index c18bcd7..63d9eda 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProviderFactory.java @@ -1,5 +1,7 @@ package org.gcube.smartgears.security; +import org.gcube.common.security.credentials.Credentials; + public interface AuthorizationProviderFactory { T connect(Credentials credentials); diff --git a/src/main/java/org/gcube/smartgears/security/Credentials.java b/src/main/java/org/gcube/smartgears/security/Credentials.java deleted file mode 100644 index 088a338..0000000 --- a/src/main/java/org/gcube/smartgears/security/Credentials.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.gcube.smartgears.security; - -public interface Credentials { - -} diff --git a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java index b9aca8b..58ca17b 100644 --- a/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java +++ b/src/main/java/org/gcube/smartgears/security/SimpleCredentials.java @@ -1,5 +1,6 @@ package org.gcube.smartgears.security; +import org.gcube.common.security.credentials.Credentials; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java index ba7fddf..e9d6cb3 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProviderFactory.java @@ -1,8 +1,8 @@ package org.gcube.smartgears.security.defaults; +import org.gcube.common.security.credentials.Credentials; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.smartgears.security.AuthorizationProviderFactory; -import org.gcube.smartgears.security.Credentials; import org.gcube.smartgears.security.SimpleCredentials; public class DefaultAuthorizationProviderFactory implements AuthorizationProviderFactory{ From 551740212f354d5685492c26b58c0c8010c52f9b Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Wed, 3 Aug 2022 12:29:53 +0200 Subject: [PATCH 34/49] put context logs to debug --- .../security/defaults/DefaultAuthorizationProvider.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index 65363d5..ace0f68 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -44,7 +44,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { try { ContextBean scope = new ContextBean(context.replaceAll("%2F", "/")); contexts.add(scope.toString()); - LOG.info("found context {}",context); + LOG.debug("found context {}",context); }catch (IllegalArgumentException e) { LOG.warn("invalid context found in token: {}", context); } From c92f119a0c031d34fe3ddbbd36ebc5a408095931 Mon Sep 17 00:00:00 2001 From: lucio Date: Thu, 22 Sep 2022 11:27:40 +0200 Subject: [PATCH 35/49] adde validation on acess token --- .../application/request/RequestValidator.java | 26 ++++++++++++++----- .../security/AuthorizationProvider.java | 3 +++ .../DefaultAuthorizationProvider.java | 2 -- 3 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index e8df27a..f2a8267 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -7,6 +7,9 @@ import static org.gcube.smartgears.handlers.application.request.RequestError.inv import java.util.Set; +import org.gcube.common.keycloak.KeycloakClient; +import org.gcube.common.keycloak.KeycloakClientException; +import org.gcube.common.keycloak.KeycloakClientFactory; import org.gcube.common.security.ContextBean; import org.gcube.common.security.ContextBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; @@ -20,6 +23,7 @@ import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.handlers.application.RequestEvent; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.ResponseEvent; +import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,9 +46,9 @@ public class RequestValidator extends RequestHandler { log.trace("executing request validator ON REQUEST"); appContext = call.context(); - + SecretManagerProvider.instance.set(getSecret(call)); - + validateAgainstLifecycle(call); rejectUnauthorizedCalls(call); @@ -116,7 +120,7 @@ public class RequestValidator extends RequestHandler { } private void validatePolicy(RequestEvent call){ - //TODO: must be rethought + //TODO: must be re-thought } private Secret getSecret(RequestEvent call){ @@ -126,16 +130,26 @@ public class RequestValidator extends RequestHandler { log.trace("authorization header is {}",authHeader); log.trace("token header is {}", token); + log.info("d4s-user set to {} ", call.request().getHeader("d4s-user")); + String accessToken = null; if (authHeader!=null && !authHeader.isEmpty()) if (authHeader.startsWith(BEARER_AUTH_PREFIX)) accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); Secret secret = null; - if (accessToken!=null) + if (accessToken!=null) { secret = new AccessTokenSecret(accessToken); - else if (token!=null) - secret = new GCubeSecret(token); + SimpleCredentials credentials = (SimpleCredentials)appContext.container().configuration().authorizationProvider().getCredentials(); + KeycloakClient client = KeycloakClientFactory.newInstance(); + try { + if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), accessToken)) + invalid_request_error.fire("access token verification error"); + }catch (KeycloakClientException e) { + RequestError.internal_server_error.fire("error contacting keycloak client", e); + } + } else if (token!=null) + secret = new GCubeSecret(token); return secret; } diff --git a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java index 2393a5f..d18e436 100644 --- a/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/AuthorizationProvider.java @@ -2,6 +2,7 @@ package org.gcube.smartgears.security; import java.util.Set; +import org.gcube.common.security.credentials.Credentials; import org.gcube.common.security.secrets.Secret; public interface AuthorizationProvider { @@ -9,4 +10,6 @@ public interface AuthorizationProvider { Set getContexts(); Secret getSecretForContext(String context); + + Credentials getCredentials(); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index 65363d5..8e9f221 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -70,8 +70,6 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { } - @Deprecated - //TODO: remove when whnManager will be removed public SimpleCredentials getCredentials() { return credentials; } From b5f6959da4f28a0182afa5b97302e079ff0ecdf0 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Mon, 24 Oct 2022 12:47:30 +0200 Subject: [PATCH 36/49] check on empty token adde --- .../handlers/application/request/RequestValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index e8df27a..5b9aee8 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -134,7 +134,7 @@ public class RequestValidator extends RequestHandler { Secret secret = null; if (accessToken!=null) secret = new AccessTokenSecret(accessToken); - else if (token!=null) + else if (token!=null && !token.isEmpty()) secret = new GCubeSecret(token); return secret; } From 1cf09963a2d293ff50f2718b1e6e4160c5cd6cb6 Mon Sep 17 00:00:00 2001 From: Luca Frosini Date: Wed, 16 Nov 2022 11:40:24 +0100 Subject: [PATCH 37/49] Fixed pom to properly compile with JDK 11 --- pom.xml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/pom.xml b/pom.xml index 562539a..f405712 100644 --- a/pom.xml +++ b/pom.xml @@ -115,6 +115,14 @@ 4.0.1 provided
+ + + + javax.xml.bind + jaxb-api + provided + + From e7aabc3fb8de97196977dd028edf9d57921e6d63 Mon Sep 17 00:00:00 2001 From: lucio lelii Date: Thu, 15 Dec 2022 16:33:44 +0100 Subject: [PATCH 38/49] fired exception on expired token modified --- .../handlers/application/request/RequestValidator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index a8f7c5a..28a80ea 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -144,7 +144,7 @@ public class RequestValidator extends RequestHandler { KeycloakClient client = KeycloakClientFactory.newInstance(); try { if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), accessToken)) - invalid_request_error.fire("access token verification error"); + RequestError.request_not_authorized_error.fire("access token verification error"); }catch (KeycloakClientException e) { RequestError.internal_server_error.fire("error contacting keycloak client", e); } From de2c95f13403ddf02c46a7a5f05a39d6ed54aedf Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 16 Dec 2022 10:01:56 +0100 Subject: [PATCH 39/49] added compiler version --- pom.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f405712..fdd083b 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,9 @@ distro 8.0.42 2.25.1 - UTF-8 + UTF-8 + 1.8 + 1.8 From d12e4a33b294023074b55a9e514b0508deb4735a Mon Sep 17 00:00:00 2001 From: lucio Date: Thu, 19 Jan 2023 16:16:14 +0100 Subject: [PATCH 40/49] AuthorizationProvider moved from Configuration to context --- pom.xml | 1 - .../AuthorizationProviderConfiguration.java | 37 +++++++++++++++++++ .../container/ContainerConfiguration.java | 33 ++++++++++------- .../ContainerConfigurationBinder.java | 7 ++-- .../application/ApplicationContext.java | 8 +++- .../DefaultApplicationContext.java | 11 ++++++ .../context/container/ContainerContext.java | 4 +- .../container/DefaultContainerContext.java | 9 ++++- .../lifecycle/ApplicationProfileManager.java | 2 +- .../application/request/RequestValidator.java | 4 +- .../lifecycle/ContainerProfileManager.java | 2 +- .../smartgears/managers/ContainerManager.java | 2 +- .../smartgears/provider/DefaultProvider.java | 16 ++++++-- .../gcube/smartgears/provider/Provider.java | 7 +--- 14 files changed, 105 insertions(+), 38 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/configuration/AuthorizationProviderConfiguration.java diff --git a/pom.xml b/pom.xml index fdd083b..ca29b5e 100644 --- a/pom.xml +++ b/pom.xml @@ -122,7 +122,6 @@ javax.xml.bind jaxb-api - provided diff --git a/src/main/java/org/gcube/smartgears/configuration/AuthorizationProviderConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/AuthorizationProviderConfiguration.java new file mode 100644 index 0000000..01cda29 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/AuthorizationProviderConfiguration.java @@ -0,0 +1,37 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.common.security.credentials.Credentials; +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.security.AuthorizationProviderFactory; + +public class AuthorizationProviderConfiguration { + + @NotNull @NotEmpty + AuthorizationProviderFactory authProviderFactory; + + @NotNull @NotEmpty + Credentials credentials; + + public AuthorizationProviderConfiguration(AuthorizationProviderFactory authProviderFactory, + Credentials credentials) { + super(); + this.authProviderFactory = authProviderFactory; + this.credentials = credentials; + } + + public AuthorizationProviderFactory getAuthProviderFactory() { + return authProviderFactory; + } + + public Credentials getCredentials() { + return credentials; + } + + @Override + public String toString() { + return "AuthorizationProviderConfiguration [authProviderFactory=" + authProviderFactory.getClass() + "]"; + } + + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index 6744a73..c749e9f 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -12,6 +12,7 @@ import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; @@ -26,8 +27,6 @@ import org.gcube.smartgears.security.AuthorizationProvider; */ public class ContainerConfiguration { - - @NotNull @IsValid private BaseConfiguration baseConfiguration; @@ -45,12 +44,13 @@ public class ContainerConfiguration { private List apps = new ArrayList(); + @NotNull @IsValid private PersistenceWriter persistenceManager; @NotNull @IsValid - private AuthorizationProvider authorizationProvider; + private AuthorizationProviderConfiguration authorizationConfiguration; protected void setBaseConfiguration(BaseConfiguration baseConfiguration) { @@ -77,8 +77,13 @@ public class ContainerConfiguration { this.persistenceManager = persistenceManager; } - protected void setAuthorizationProvider(AuthorizationProvider authorizationProvider) { - this.authorizationProvider = authorizationProvider; + protected void setAuthorizationProviderConfiguration( + AuthorizationProviderConfiguration authorizationConfiguration) { + this.authorizationConfiguration = authorizationConfiguration; + } + + public void setApps(List apps) { + this.apps = apps; } /** @@ -178,14 +183,6 @@ public class ContainerConfiguration { return baseConfiguration.isAuthorizeChildrenContext(); } - /** - * Returns the credentials. - * @return the credentials - */ - public AuthorizationProvider authorizationProvider() { - return authorizationProvider; - } - /** * Returns the proxy of the container. * @return the proxy @@ -211,6 +208,14 @@ public class ContainerConfiguration { return accountingFallbackLocation; } + /** + * Returns the authorization configuration. + * @return AuthorizationProviderConfiguration the configuration + */ + public AuthorizationProviderConfiguration getauthorizationConfiguration() { + return authorizationConfiguration; + } + /** * Returns the configuration properties of the container. * @return the properties @@ -251,7 +256,7 @@ public class ContainerConfiguration { return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties + ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation + ", persistenceManager=" + persistenceManager.getClass().getSimpleName() - + ", authorizationProvider=" + authorizationProvider.getClass().getSimpleName() + "]"; + + ", authorizationProvider=" + authorizationConfiguration + "]"; } diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 95cc640..14d3f68 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -9,6 +9,7 @@ import java.util.Map.Entry; import java.util.stream.Collectors; import org.gcube.common.security.credentials.Credentials; +import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; @@ -139,10 +140,8 @@ public class ContainerConfigurationBinder { throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e); } authorizationSection.to(credentials, "credentials."); - - AuthorizationProvider authProvider = authProviderFactory.connect(credentials); - - conf.setAuthorizationProvider(authProvider); + + conf.setAuthorizationProviderConfiguration(new AuthorizationProviderConfiguration(authProviderFactory, credentials)); } } diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java index d213e29..399cead 100644 --- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java @@ -8,6 +8,7 @@ import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; /** * The management context of an application. @@ -75,6 +76,11 @@ public interface ApplicationContext { * @return the properties */ Properties properties(); - + + /** + * Returns the authorization provider. + * @return the AuhtorizationProvider + **/ + AuthorizationProvider authorizationProvider(); } diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 2592ca9..386d330 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -8,6 +8,7 @@ import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; /** * Default {@link ApplicationContext} implementation. @@ -87,6 +88,8 @@ public class DefaultApplicationContext implements ApplicationContext { return configuration.persistence(); } + + @Override public Properties properties() { return properties; @@ -97,4 +100,12 @@ public class DefaultApplicationContext implements ApplicationContext { return id; } + /** + * Returns the authorization provider. + * @return the AuhtorizationProvider + **/ + public AuthorizationProvider authorizationProvider() { + return container().authorizationProvider(); + } + } diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index 3eecf4a..9cc70da 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -1,11 +1,11 @@ package org.gcube.smartgears.context.container; import org.gcube.common.events.Hub; -import org.gcube.common.resources.gcore.HostingNode; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; /** * The management context of the container. @@ -48,5 +48,7 @@ public interface ContainerContext { Properties properties(); String id(); + + AuthorizationProvider authorizationProvider(); } diff --git a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java index 64fbfac..0cf4ad4 100644 --- a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java @@ -8,6 +8,7 @@ import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.smartgears.security.AuthorizationProvider; /** * Default {@link ContainerContext} implementation. @@ -21,6 +22,7 @@ public class DefaultContainerContext implements ContainerContext { private final ContainerLifecycle lifecycle; private final Properties properties; private final Hub hub; + private final AuthorizationProvider authorizationProvider; private final String id; /** * Creates an instance with mandatory parameters. @@ -29,13 +31,14 @@ public class DefaultContainerContext implements ContainerContext { * @param lifecycle the lifecycle * @param properties the properties */ - public DefaultContainerContext(String id,ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle, + public DefaultContainerContext(String id,ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle, AuthorizationProvider authProvider, Properties properties) { this.id = id; this.configuration=configuration; this.hub=hub; this.lifecycle = lifecycle; this.properties=properties; + this.authorizationProvider = authProvider; } public HostingNode profile() { @@ -72,6 +75,8 @@ public class DefaultContainerContext implements ContainerContext { return id; } - + public AuthorizationProvider authorizationProvider() { + return authorizationProvider; + } } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 5528d18..25d2cf1 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -124,7 +124,7 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { publishers.forEach(p -> { try { p.create(context, - context.container().configuration().authorizationProvider().getContexts()); + context.container().authorizationProvider().getContexts()); }catch (Exception e) { log.error("cannot publish {} for first time with publisher type {} (see details)",context.name(), p.getClass().getCanonicalName(), e); } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 28a80ea..1ec7266 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -95,7 +95,7 @@ public class RequestValidator extends RequestHandler { ContextBean bean = new ContextBean(context); ContainerConfiguration conf = appContext.container().configuration(); - Set allowedContexts =conf.authorizationProvider().getContexts(); + Set allowedContexts =appContext.authorizationProvider().getContexts(); if (!allowedContexts.contains(context) && !(conf.authorizeChildrenContext() && bean.is(Type.VRE) && allowedContexts.contains(bean.enclosingScope().toString()) ) ) { @@ -140,7 +140,7 @@ public class RequestValidator extends RequestHandler { Secret secret = null; if (accessToken!=null) { secret = new AccessTokenSecret(accessToken); - SimpleCredentials credentials = (SimpleCredentials)appContext.container().configuration().authorizationProvider().getCredentials(); + SimpleCredentials credentials = (SimpleCredentials)appContext.authorizationProvider().getCredentials(); KeycloakClient client = KeycloakClientFactory.newInstance(); try { if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), accessToken)) diff --git a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java index 80adbd9..58440b0 100644 --- a/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/container/lifecycle/ContainerProfileManager.java @@ -111,7 +111,7 @@ public class ContainerProfileManager extends ContainerHandler { publishers.forEach(p -> { try { p.create(context, - context.configuration().authorizationProvider().getContexts()); + context.authorizationProvider().getContexts()); }catch (Exception e) { log.error("cannot publish container for first time with publisher type {} (see details)", p.getClass().getCanonicalName(), e); } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 4dc0bb3..5db0195 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -102,7 +102,7 @@ public class ContainerManager { Set foundContexts; try { - foundContexts = context.configuration().authorizationProvider().getContexts(); + foundContexts = context.authorizationProvider().getContexts(); } catch (Exception e) { log.error("error authorizing container",e); throw new RuntimeException("error authorizing container, moving the container to failed",e); diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index cfc6eb9..6b092bd 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -25,6 +25,7 @@ import javax.servlet.ServletContext; import org.gcube.common.events.Hub; import org.gcube.common.events.impl.DefaultHub; +import org.gcube.common.security.credentials.Credentials; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; import org.gcube.smartgears.configuration.application.ApplicationExtensions; @@ -45,6 +46,7 @@ import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; import org.gcube.smartgears.publishing.Publisher; import org.gcube.smartgears.publishing.SmartgearsProfilePublisher; import org.gcube.smartgears.security.AuthorizationProvider; +import org.gcube.smartgears.security.AuthorizationProviderFactory; import org.gcube.smartgears.utils.Utils; import org.reflections.Reflections; import org.reflections.scanners.SubTypesScanner; @@ -107,7 +109,12 @@ public class DefaultProvider implements Provider { } - containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, new Properties()); + AuthorizationProviderFactory authfactory = configuration.getauthorizationConfiguration().getAuthProviderFactory(); + Credentials credentials = configuration.getauthorizationConfiguration().getCredentials(); + + AuthorizationProvider authProvider = authfactory.connect(credentials); + + containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, new Properties()); } return containerContext; } @@ -373,10 +380,11 @@ public class DefaultProvider implements Provider { return this.publishers; } - +/* @Override public AuthorizationProvider authorizationProvider() { - return containerContext.configuration().authorizationProvider(); + return containerContext.authorizationProvider(); } - +*/ + } diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index 1f95b22..3b6b694 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -72,11 +72,6 @@ public interface Provider { * @return the extensions */ ApplicationExtensions extensionsFor(ApplicationContext application); - - /** - * Returns the authorization provider for this node - * @return the AuthorizationProvider implementation - */ - AuthorizationProvider authorizationProvider(); + } From 29e02ac5870b8db7b1d193e8510ccbf147e807e6 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 23 Jan 2023 15:41:21 +0100 Subject: [PATCH 41/49] removed old import --- .../configuration/container/ContainerConfiguration.java | 1 - .../configuration/container/ContainerConfigurationBinder.java | 1 - .../smartgears/extensions/resource/FrontPageResource.java | 3 --- src/main/java/org/gcube/smartgears/provider/Provider.java | 1 - 4 files changed, 6 deletions(-) diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index c749e9f..0fef04c 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -17,7 +17,6 @@ import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.persistence.PersistenceWriter; -import org.gcube.smartgears.security.AuthorizationProvider; /** * The configuration of the container. diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 14d3f68..599d605 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -16,7 +16,6 @@ import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager; import org.gcube.smartgears.persistence.LocalPersistence; import org.gcube.smartgears.persistence.PersistenceWriter; -import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.AuthorizationProviderFactory; import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory; import org.gcube.smartgears.utils.Utils; diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index 6fa5b37..fdbd49c 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -12,9 +12,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.HashMap; -import java.util.HashSet; import java.util.Map; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -22,7 +20,6 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.security.ContextBean; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; import org.slf4j.Logger; diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index 3b6b694..fc80175 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -11,7 +11,6 @@ import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.publishing.Publisher; -import org.gcube.smartgears.security.AuthorizationProvider; /** * Provides dependencies for container and application management. From 3407ce025c2a3e2a0615f638413f4c8626e4deed Mon Sep 17 00:00:00 2001 From: lucio Date: Thu, 26 Jan 2023 18:24:18 +0100 Subject: [PATCH 42/49] health objects added --- pom.xml | 8 +-- .../extensions/resource/HealthResource.java | 44 +++++++++++++ .../extensions/resource/RemoteResource.java | 4 +- .../gcube/smartgears/health/HealthCheck.java | 9 +++ .../health/KeyCloakHealthCheck.java | 25 +++++++ .../smartgears/health/ReadinessChecker.java | 12 ++++ .../org/gcube/smartgears/health/Status.java | 6 ++ .../health/response/HealthCheckResponse.java | 30 +++++++++ .../response/HealthCheckResponseBuilder.java | 65 +++++++++++++++++++ .../health/response/HealthResponse.java | 18 +++++ .../response/HealthResponseBuilder.java | 13 ++++ 11 files changed, 228 insertions(+), 6 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java create mode 100644 src/main/java/org/gcube/smartgears/health/HealthCheck.java create mode 100644 src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java create mode 100644 src/main/java/org/gcube/smartgears/health/ReadinessChecker.java create mode 100644 src/main/java/org/gcube/smartgears/health/Status.java create mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java create mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java create mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthResponse.java create mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java diff --git a/pom.xml b/pom.xml index ca29b5e..37a5489 100644 --- a/pom.xml +++ b/pom.xml @@ -31,7 +31,7 @@ distro 8.0.42 2.25.1 - UTF-8 + UTF-8 1.8 1.8 @@ -117,11 +117,11 @@ 4.0.1 provided - + - javax.xml.bind - jaxb-api + javax.xml.bind + jaxb-api diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java new file mode 100644 index 0000000..d3d5394 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -0,0 +1,44 @@ +package org.gcube.smartgears.extensions.resource; + +import static org.gcube.smartgears.Constants.application_json; +import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.gcube.smartgears.extensions.ApiResource; +import org.gcube.smartgears.extensions.ApiSignature; +import org.gcube.smartgears.health.response.HealthResponse; + +public class HealthResource extends ApiResource { + + private static final long serialVersionUID = 1L; + + public static final String mapping = "/health"; + + private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json)); + + + HealthResource() { + super(signature); + } + + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + + } + + + public HealthResponse liveness() { + return null; + } + + public HealthResponse readiness() { + return null; + } + +} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java index 475c1d8..f160cae 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java @@ -1,6 +1,6 @@ package org.gcube.smartgears.extensions.resource; -import static org.gcube.smartgears.Constants.*; +import static org.gcube.smartgears.Constants.remote_management; import javax.xml.bind.annotation.XmlRootElement; @@ -27,7 +27,7 @@ public class RemoteResource extends HttpController { public RemoteResource() { super(remote_management, default_mapping); addResources(new FrontPageResource(), new ConfigurationResource(), new ProfileResource(), - new LifecycleResource(), new MetricsResource()); + new LifecycleResource(), new MetricsResource(), new HealthResource()); } @Override diff --git a/src/main/java/org/gcube/smartgears/health/HealthCheck.java b/src/main/java/org/gcube/smartgears/health/HealthCheck.java new file mode 100644 index 0000000..b3f992b --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/HealthCheck.java @@ -0,0 +1,9 @@ +package org.gcube.smartgears.health; + +import org.gcube.smartgears.health.response.HealthCheckResponse; + +public interface HealthCheck { + + HealthCheckResponse check(); + +} diff --git a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java new file mode 100644 index 0000000..15fd0aa --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java @@ -0,0 +1,25 @@ +package org.gcube.smartgears.health; + +import java.util.Set; + +import org.gcube.smartgears.health.response.HealthCheckResponse; +import org.gcube.smartgears.provider.ProviderFactory; + +@ReadinessChecker +public class KeyCloakHealthCheck implements HealthCheck{ + + private static final String CHECK_NAME = "authorizationCheck" ; + + @Override + public HealthCheckResponse check() { + try { + Set contexts = ProviderFactory.provider().containerContext().authorizationProvider().getContexts(); + if (contexts.isEmpty()) + return HealthCheckResponse.builder(CHECK_NAME).down().withMessage("no contexts are defined for this server").build(); + return HealthCheckResponse.builder(CHECK_NAME).up().build(); + }catch (Exception e) { + return HealthCheckResponse.builder(CHECK_NAME).down().withMessage(e.getMessage()).build(); + } + } + +} diff --git a/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java b/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java new file mode 100644 index 0000000..6483255 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java @@ -0,0 +1,12 @@ +package org.gcube.smartgears.health; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.TYPE) +public @interface ReadinessChecker { + +} diff --git a/src/main/java/org/gcube/smartgears/health/Status.java b/src/main/java/org/gcube/smartgears/health/Status.java new file mode 100644 index 0000000..1ecaef1 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/Status.java @@ -0,0 +1,6 @@ +package org.gcube.smartgears.health; + +public enum Status { + + UP, DOWN, NOT_CALCULATED +} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java new file mode 100644 index 0000000..33bcdf7 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java @@ -0,0 +1,30 @@ +package org.gcube.smartgears.health.response; + +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.health.Status; + +@JsonInclude(Include.NON_NULL) +public class HealthCheckResponse { + + public static HealthCheckResponseBuilder builder(String checkName) { + return new HealthCheckResponseBuilder(checkName); + } + + protected HealthCheckResponse() {} + + //enum ErrorType {UNRECOVERABLE, RECOVERABLE} + + @NotNull + protected Status status; + + @NotNull @NotEmpty + protected String name; + + //protected ErrorType errorType; + + protected String errorMessage; + +} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java new file mode 100644 index 0000000..266e0a2 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java @@ -0,0 +1,65 @@ +package org.gcube.smartgears.health.response; + +import java.util.ArrayList; +import java.util.List; + +import org.gcube.common.validator.ValidationError; +import org.gcube.common.validator.Validator; +import org.gcube.common.validator.ValidatorFactory; +import org.gcube.smartgears.health.Status; + +public class HealthCheckResponseBuilder { + + private HealthCheckResponse healthCheckResponse = new HealthCheckResponse(); + + protected HealthCheckResponseBuilder(String name) { + healthCheckResponse.name = name; + } + + public BuildPart up() { + healthCheckResponse.status = Status.UP; + return new BuildPart(); + } + + public ErrorPart down() { + healthCheckResponse.status = Status.DOWN; + return new ErrorPart(); + } + + private void validateResponse() { + + List msgs = new ArrayList(); + + Validator validator = ValidatorFactory.validator(); + + for (ValidationError error : validator.validate(healthCheckResponse)) + msgs.add(error.toString()); + + if (!msgs.isEmpty()) + throw new IllegalStateException("invalid configuration: "+msgs); + + } + + public class ErrorPart{ + + private ErrorPart() {} + + public BuildPart withMessage(String message) { + healthCheckResponse.errorMessage = message; + return new BuildPart(); + } + + } + + public class BuildPart{ + + private BuildPart() {}; + + public HealthCheckResponse build() { + validateResponse(); + return healthCheckResponse; + } + + } + +} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java b/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java new file mode 100644 index 0000000..8321d1f --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java @@ -0,0 +1,18 @@ +package org.gcube.smartgears.health.response; + +import java.util.List; + +import org.gcube.smartgears.health.HealthCheck; +import org.gcube.smartgears.health.Status; + +public class HealthResponse { + + Status status; + + List checks; + + void register(HealthCheck check){ + checks.add(check); + } + +} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java b/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java new file mode 100644 index 0000000..4077c85 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java @@ -0,0 +1,13 @@ +package org.gcube.smartgears.health.response; + +public class HealthResponseBuilder { + + private HealthResponse healthResponse; + + public HealthResponse build() { + return healthResponse; + } + + + +} From 98c41e74635f7ce9babc1f87e07d035e83a334bc Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 27 Jan 2023 17:01:22 +0100 Subject: [PATCH 43/49] moved health part to a separate library --- pom.xml | 49 ++------------ .../extensions/resource/HealthResource.java | 2 +- .../gcube/smartgears/health/HealthCheck.java | 9 --- .../health/KeyCloakHealthCheck.java | 8 ++- .../smartgears/health/ReadinessChecker.java | 12 ---- .../org/gcube/smartgears/health/Status.java | 6 -- .../health/response/HealthCheckResponse.java | 30 --------- .../response/HealthCheckResponseBuilder.java | 65 ------------------- .../health/response/HealthResponse.java | 18 ----- .../response/HealthResponseBuilder.java | 13 ---- 10 files changed, 12 insertions(+), 200 deletions(-) delete mode 100644 src/main/java/org/gcube/smartgears/health/HealthCheck.java delete mode 100644 src/main/java/org/gcube/smartgears/health/ReadinessChecker.java delete mode 100644 src/main/java/org/gcube/smartgears/health/Status.java delete mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java delete mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java delete mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthResponse.java delete mode 100644 src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java diff --git a/pom.xml b/pom.xml index 37a5489..d929d94 100644 --- a/pom.xml +++ b/pom.xml @@ -8,13 +8,10 @@ 1.1.0 - org.gcube.core common-smartgears 4.0.0-SNAPSHOT - SmartGears - @@ -26,7 +23,6 @@ - distro 8.0.42 @@ -35,21 +31,22 @@ 1.8 1.8 - scm:git:https://code-repo.d4science.org/gCubeSystem/common-smartgears.git - scm:git:https://code-repo.d4science.org/gCubeSystem/common-smartgears.git + scm:git:httpstps://code-repo.d4science.org/gCubeSystem/common-smartgears.git https://code-repo.d4science.org/gCubeSystem/common-smartgears - - org.reflections reflections 0.9.10 - + + org.gcube.common + health-api + 1.0.0-SNAPSHOT + org.gcube.common @@ -68,40 +65,33 @@ org.gcube.common common-security - org.gcube.data.publishing document-store-lib - org.gcube.accounting accounting-lib - org.slf4j slf4j-api - org.ini4j ini4j 0.5.4 - org.gcube.core common-validator [1.0.0,2.0.0-SNAPSHOT) - org.gcube.core common-events [1.0.0,2.0.0-SNAPSHOT) - org.gcube.common.security gcube-secrets @@ -110,37 +100,30 @@ javax.ws.rs javax.ws.rs-api - javax.servlet javax.servlet-api 4.0.1 provided - javax.xml.bind jaxb-api - io.micrometer micrometer-core 1.9.0 - io.micrometer micrometer-registry-prometheus 1.9.0 - - - org.jboss.shrinkwrap.resolver shrinkwrap-resolver-depchain @@ -148,7 +131,6 @@ pom test - org.apache.tomcat @@ -156,66 +138,54 @@ ${tomcat.version} provided - org.apache.tomcat.embed tomcat-embed-core ${tomcat.version} test - org.glassfish.jersey.core jersey-client test - - org.apache.tomcat.embed tomcat-embed-core ${tomcat.version} test - org.apache.tomcat.embed tomcat-embed-logging-log4j ${tomcat.version} test - org.apache.tomcat.embed tomcat-embed-jasper ${tomcat.version} test - junit junit 4.10 test - ch.qos.logback logback-classic runtime - org.mockito mockito-core 1.9.0 test - - - @@ -236,7 +206,6 @@ - org.apache.maven.plugins maven-surefire-plugin @@ -249,8 +218,6 @@ - - org.apache.maven.plugins @@ -259,7 +226,6 @@ false probe - WEB-INF/classes/org/gcube/smartgears/probe/**/* false @@ -273,8 +239,6 @@ - - org.apache.maven.plugins maven-surefire-plugin @@ -311,7 +275,6 @@ - diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java index d3d5394..2f0b997 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -9,9 +9,9 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import org.gcube.common.health.api.response.HealthResponse; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; -import org.gcube.smartgears.health.response.HealthResponse; public class HealthResource extends ApiResource { diff --git a/src/main/java/org/gcube/smartgears/health/HealthCheck.java b/src/main/java/org/gcube/smartgears/health/HealthCheck.java deleted file mode 100644 index b3f992b..0000000 --- a/src/main/java/org/gcube/smartgears/health/HealthCheck.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.gcube.smartgears.health; - -import org.gcube.smartgears.health.response.HealthCheckResponse; - -public interface HealthCheck { - - HealthCheckResponse check(); - -} diff --git a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java index 15fd0aa..1a78f73 100644 --- a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java +++ b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java @@ -2,20 +2,22 @@ package org.gcube.smartgears.health; import java.util.Set; -import org.gcube.smartgears.health.response.HealthCheckResponse; +import org.gcube.common.health.api.HealthCheck; +import org.gcube.common.health.api.ReadinessChecker; +import org.gcube.common.health.api.response.HealthCheckResponse; import org.gcube.smartgears.provider.ProviderFactory; @ReadinessChecker public class KeyCloakHealthCheck implements HealthCheck{ - private static final String CHECK_NAME = "authorizationCheck" ; + private static final String CHECK_NAME = "authorization-check" ; @Override public HealthCheckResponse check() { try { Set contexts = ProviderFactory.provider().containerContext().authorizationProvider().getContexts(); if (contexts.isEmpty()) - return HealthCheckResponse.builder(CHECK_NAME).down().withMessage("no contexts are defined for this server").build(); + return HealthCheckResponse.builder(CHECK_NAME).down().withMessage("no contexts are defined for the client id provided").build(); return HealthCheckResponse.builder(CHECK_NAME).up().build(); }catch (Exception e) { return HealthCheckResponse.builder(CHECK_NAME).down().withMessage(e.getMessage()).build(); diff --git a/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java b/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java deleted file mode 100644 index 6483255..0000000 --- a/src/main/java/org/gcube/smartgears/health/ReadinessChecker.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.gcube.smartgears.health; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface ReadinessChecker { - -} diff --git a/src/main/java/org/gcube/smartgears/health/Status.java b/src/main/java/org/gcube/smartgears/health/Status.java deleted file mode 100644 index 1ecaef1..0000000 --- a/src/main/java/org/gcube/smartgears/health/Status.java +++ /dev/null @@ -1,6 +0,0 @@ -package org.gcube.smartgears.health; - -public enum Status { - - UP, DOWN, NOT_CALCULATED -} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java deleted file mode 100644 index 33bcdf7..0000000 --- a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponse.java +++ /dev/null @@ -1,30 +0,0 @@ -package org.gcube.smartgears.health.response; - -import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; -import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; -import org.gcube.common.validator.annotations.NotEmpty; -import org.gcube.common.validator.annotations.NotNull; -import org.gcube.smartgears.health.Status; - -@JsonInclude(Include.NON_NULL) -public class HealthCheckResponse { - - public static HealthCheckResponseBuilder builder(String checkName) { - return new HealthCheckResponseBuilder(checkName); - } - - protected HealthCheckResponse() {} - - //enum ErrorType {UNRECOVERABLE, RECOVERABLE} - - @NotNull - protected Status status; - - @NotNull @NotEmpty - protected String name; - - //protected ErrorType errorType; - - protected String errorMessage; - -} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java b/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java deleted file mode 100644 index 266e0a2..0000000 --- a/src/main/java/org/gcube/smartgears/health/response/HealthCheckResponseBuilder.java +++ /dev/null @@ -1,65 +0,0 @@ -package org.gcube.smartgears.health.response; - -import java.util.ArrayList; -import java.util.List; - -import org.gcube.common.validator.ValidationError; -import org.gcube.common.validator.Validator; -import org.gcube.common.validator.ValidatorFactory; -import org.gcube.smartgears.health.Status; - -public class HealthCheckResponseBuilder { - - private HealthCheckResponse healthCheckResponse = new HealthCheckResponse(); - - protected HealthCheckResponseBuilder(String name) { - healthCheckResponse.name = name; - } - - public BuildPart up() { - healthCheckResponse.status = Status.UP; - return new BuildPart(); - } - - public ErrorPart down() { - healthCheckResponse.status = Status.DOWN; - return new ErrorPart(); - } - - private void validateResponse() { - - List msgs = new ArrayList(); - - Validator validator = ValidatorFactory.validator(); - - for (ValidationError error : validator.validate(healthCheckResponse)) - msgs.add(error.toString()); - - if (!msgs.isEmpty()) - throw new IllegalStateException("invalid configuration: "+msgs); - - } - - public class ErrorPart{ - - private ErrorPart() {} - - public BuildPart withMessage(String message) { - healthCheckResponse.errorMessage = message; - return new BuildPart(); - } - - } - - public class BuildPart{ - - private BuildPart() {}; - - public HealthCheckResponse build() { - validateResponse(); - return healthCheckResponse; - } - - } - -} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java b/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java deleted file mode 100644 index 8321d1f..0000000 --- a/src/main/java/org/gcube/smartgears/health/response/HealthResponse.java +++ /dev/null @@ -1,18 +0,0 @@ -package org.gcube.smartgears.health.response; - -import java.util.List; - -import org.gcube.smartgears.health.HealthCheck; -import org.gcube.smartgears.health.Status; - -public class HealthResponse { - - Status status; - - List checks; - - void register(HealthCheck check){ - checks.add(check); - } - -} diff --git a/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java b/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java deleted file mode 100644 index 4077c85..0000000 --- a/src/main/java/org/gcube/smartgears/health/response/HealthResponseBuilder.java +++ /dev/null @@ -1,13 +0,0 @@ -package org.gcube.smartgears.health.response; - -public class HealthResponseBuilder { - - private HealthResponse healthResponse; - - public HealthResponse build() { - return healthResponse; - } - - - -} From b873f971872f792ccd0d51a714e114c08a00bf30 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 1 Feb 2023 14:40:31 +0100 Subject: [PATCH 44/49] Health extension implemented --- pom.xml | 6 +- .../application/ApplicationContext.java | 2 +- .../DefaultApplicationContext.java | 5 +- .../context/container/ContainerContext.java | 1 + .../smartgears/extensions/ApiResource.java | 2 +- .../extensions/ApplicationExtension.java | 2 + .../smartgears/extensions/HttpExtension.java | 3 + .../extensions/resource/HealthResource.java | 83 ++++++- .../smartgears/health/HealthManager.java | 18 ++ .../smartgears/health/HealthResponse.java | 35 +++ .../gcube/smartgears/health/HealthTask.java | 43 ++++ .../health/KeyCloakHealthCheck.java | 4 + .../managers/ApplicationManager.java | 19 +- .../smartgears/provider/DefaultProvider.java | 206 ++++++++++-------- 14 files changed, 318 insertions(+), 111 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/health/HealthManager.java create mode 100644 src/main/java/org/gcube/smartgears/health/HealthResponse.java create mode 100644 src/main/java/org/gcube/smartgears/health/HealthTask.java diff --git a/pom.xml b/pom.xml index d929d94..7320a92 100644 --- a/pom.xml +++ b/pom.xml @@ -38,9 +38,9 @@ - org.reflections - reflections - 0.9.10 + io.github.classgraph + classgraph + 4.8.28 org.gcube.common diff --git a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java index 399cead..949c420 100644 --- a/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/ApplicationContext.java @@ -82,5 +82,5 @@ public interface ApplicationContext { * @return the AuhtorizationProvider **/ AuthorizationProvider authorizationProvider(); - + } diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 386d330..4e0b443 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -6,6 +6,7 @@ import org.gcube.common.events.Hub; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.health.HealthManager; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; @@ -42,7 +43,7 @@ public class DefaultApplicationContext implements ApplicationContext { this.configuration=configuration; this.hub=hub; this.lifecycle = lifecycle; - this.properties=properties; + this.properties=properties; } /** @@ -106,6 +107,6 @@ public class DefaultApplicationContext implements ApplicationContext { **/ public AuthorizationProvider authorizationProvider() { return container().authorizationProvider(); - } + } } diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index 9cc70da..454a94a 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -51,4 +51,5 @@ public interface ContainerContext { AuthorizationProvider authorizationProvider(); + } diff --git a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java index 6fab2bd..a49eb27 100644 --- a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java @@ -56,7 +56,7 @@ public abstract class ApiResource extends HttpExtension { public Set excludes() { return Collections.singleton(new Exclude(Constants.root_mapping+mapping())); } - + /** * Returns true if this resource supports a given method. * @param method the method diff --git a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java index c4216d6..9658b4d 100644 --- a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java @@ -22,6 +22,8 @@ public interface ApplicationExtension extends Servlet { */ void init(ApplicationContext context) throws Exception; + void stop(); + /** * Returns the name of this extension. * @return the name diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java index d8edea6..f3660d2 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java @@ -76,6 +76,9 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx this.context=context; } + @Override + public void stop() {} + @Override public Set excludes() { return new HashSet(); //all managed by default diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java index 2f0b997..ef18a62 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -4,41 +4,108 @@ import static org.gcube.smartgears.Constants.application_json; import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; import java.io.IOException; +import java.io.PrintWriter; +import java.util.Set; +import java.util.Timer; +import java.util.stream.Collectors; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.health.api.response.HealthResponse; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.common.health.api.HealthCheck; +import org.gcube.common.health.api.ReadinessChecker; +import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; +import org.gcube.smartgears.handlers.application.request.RequestError; +import org.gcube.smartgears.health.HealthManager; +import org.gcube.smartgears.health.HealthResponse; +import org.gcube.smartgears.health.HealthTask; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ClassInfo; +import io.github.classgraph.ClassInfoList; +import io.github.classgraph.ScanResult; public class HealthResource extends ApiResource { private static final long serialVersionUID = 1L; + private static Logger log = LoggerFactory.getLogger(HealthResource.class); + public static final String mapping = "/health"; private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json)); - + + private HealthManager manager; + + private HealthTask task; + + private Timer timer; HealthResource() { super(signature); } - @Override - public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + public void init(ApplicationContext context) throws Exception { + Set> annotatedReadiness; + + try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo().scan()) { + + ClassInfoList classInfos = result.getClassesWithAnnotation(ReadinessChecker.class.getName()); + + annotatedReadiness = classInfos.stream().map(ClassInfo::loadClass) + .filter(c -> HealthCheck.class.isAssignableFrom(c)).collect(Collectors.toSet()); + } + manager = new HealthManager(); + for (Class readnessClass : annotatedReadiness) + try { + manager.register((HealthCheck) readnessClass.getDeclaredConstructor().newInstance()); + log.info("added class {} to health manager", readnessClass.getCanonicalName()); + } catch (Throwable e) { + log.error("healthChecher class {} cannot be instantiated", readnessClass.getCanonicalName(), e); + } + + task = new HealthTask(manager); + + timer = new Timer(true); + + timer.scheduleAtFixedRate(task, 0, 10000); + + super.init(context); } - - public HealthResponse liveness() { - return null; + public void stop() { + timer.cancel(); + } + + @Override + public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { + PrintWriter out = resp.getWriter(); + resp.setContentType("application/json"); + resp.setCharacterEncoding("UTF-8"); + Object response = null; + + String contextpath = req.getContextPath(); + log.info("context path is {}", req.getContextPath()); + if (contextpath.endsWith("/readiness")) + response = readiness(); + else + RequestError.resource_notfound_error.fire(); + + new ObjectMapper().writeValue(out, response); + + out.flush(); } public HealthResponse readiness() { - return null; + return task.getResponse(); } } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/health/HealthManager.java b/src/main/java/org/gcube/smartgears/health/HealthManager.java new file mode 100644 index 0000000..64dcab0 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/HealthManager.java @@ -0,0 +1,18 @@ +package org.gcube.smartgears.health; + +import java.util.List; + +import org.gcube.common.health.api.HealthCheck; + +public class HealthManager { + + private List checks; + + public void register(HealthCheck check){ + checks.add(check); + } + + public List getChecks() { + return checks; + } +} diff --git a/src/main/java/org/gcube/smartgears/health/HealthResponse.java b/src/main/java/org/gcube/smartgears/health/HealthResponse.java new file mode 100644 index 0000000..c1f9dbd --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/HealthResponse.java @@ -0,0 +1,35 @@ +package org.gcube.smartgears.health; + +import java.util.List; + +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; +import org.gcube.common.health.api.Status; +import org.gcube.common.health.api.response.HealthCheckResponse; +import org.gcube.common.validator.annotations.NotNull; + +@JsonInclude(Include.NON_NULL) +public class HealthResponse { + + @NotNull + private Status status; + + private List checks; + + + + public HealthResponse(Status status, List checks) { + super(); + this.status = status; + this.checks = checks; + } + + public Status getStatus() { + return status; + } + + public List getChecks() { + return checks; + } + +} diff --git a/src/main/java/org/gcube/smartgears/health/HealthTask.java b/src/main/java/org/gcube/smartgears/health/HealthTask.java new file mode 100644 index 0000000..61aa28b --- /dev/null +++ b/src/main/java/org/gcube/smartgears/health/HealthTask.java @@ -0,0 +1,43 @@ +package org.gcube.smartgears.health; + +import java.util.List; +import java.util.TimerTask; +import java.util.stream.Collectors; + +import org.gcube.common.health.api.HealthCheck; +import org.gcube.common.health.api.Status; +import org.gcube.common.health.api.response.HealthCheckResponse; + +public class HealthTask extends TimerTask{ + + private HealthResponse response; + + private HealthManager healthManager; + + public HealthTask(HealthManager healthManager) { + this.healthManager = healthManager; + } + + @Override + public void run() { + List checks = healthManager.getChecks(); + + List responses = checks.stream().map(c -> this.wrap(c)).collect(Collectors.toList()); + Status totalStatus = responses.stream().anyMatch(r -> r.getStatus().equals(Status.DOWN)) ? Status.DOWN : Status.UP; + + this.response = new HealthResponse(totalStatus, responses); + } + + public HealthResponse getResponse() { + return response; + } + + private HealthCheckResponse wrap(HealthCheck check){ + try { + return check.check(); + }catch (Throwable t) { + return HealthCheckResponse.builder(check.getName()).down().withMessage("unexpected error executing check").build(); + } + + } +} diff --git a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java index 1a78f73..fd087bf 100644 --- a/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java +++ b/src/main/java/org/gcube/smartgears/health/KeyCloakHealthCheck.java @@ -12,6 +12,10 @@ public class KeyCloakHealthCheck implements HealthCheck{ private static final String CHECK_NAME = "authorization-check" ; + public String getName(){ + return CHECK_NAME; + } + @Override public HealthCheckResponse check() { try { diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index 4f3bfe1..a1fbe26 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -13,6 +13,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.util.Collection; +import java.util.Collections; import java.util.List; import java.util.Map.Entry; @@ -52,6 +53,8 @@ public class ApplicationManager { private ApplicationContext context; + private ApplicationExtensions extensions; + /** * Starts application management. * @@ -80,7 +83,7 @@ public class ApplicationManager { ApplicationHandlers handlers = provider().handlersFor(context); - ApplicationExtensions extensions = provider().extensionsFor(context); + extensions = provider().extensionsFor(context); extensions.validate(); List lifecycleHandlers = handlers.lifecycleHandlers(); @@ -150,7 +153,10 @@ public class ApplicationManager { context.lifecycle().tryMoveTo(stopped); context.events().fire(context, ApplicationLifecycle.stop); - + + if (extensions != null) + unregister(extensions); + stopLifecycleHandlers(); log.info("stopping application events for {}", context.name()); @@ -227,6 +233,15 @@ public class ApplicationManager { } } + + private void unregister(ApplicationExtensions extensions) { + + for (ApplicationExtension extension : extensions.extensions()) + + extension.stop(); + + } + private void start(List handlers) { diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 6b092bd..1cf05c0 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -14,12 +14,11 @@ import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.ObjectInputStream; -import java.net.URL; import java.util.ArrayList; -import java.util.Collection; import java.util.List; import java.util.Set; import java.util.UUID; +import java.util.stream.Collectors; import javax.servlet.ServletContext; @@ -48,14 +47,14 @@ import org.gcube.smartgears.publishing.SmartgearsProfilePublisher; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.AuthorizationProviderFactory; import org.gcube.smartgears.utils.Utils; -import org.reflections.Reflections; -import org.reflections.scanners.SubTypesScanner; -import org.reflections.scanners.TypeAnnotationsScanner; -import org.reflections.util.ClasspathHelper; -import org.reflections.util.ConfigurationBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import io.github.classgraph.ClassGraph; +import io.github.classgraph.ClassInfo; +import io.github.classgraph.ClassInfoList; +import io.github.classgraph.ScanResult; + /** * Default implementation of the {@link Provider} interface. * @@ -67,8 +66,7 @@ public class DefaultProvider implements Provider { private static Logger log = LoggerFactory.getLogger(Provider.class); private ContainerContext containerContext; - //TODO: do the same with applicationContext (with a map) - + // TODO: do the same with applicationContext (with a map) private File configFile = null; @@ -78,13 +76,13 @@ public class DefaultProvider implements Provider { List publishers; - - protected DefaultProvider(){}; + protected DefaultProvider() { + }; @Override public ContainerContext containerContext() { - if(containerContext==null){ + if (containerContext == null) { ContainerConfiguration configuration = containerConfiguration(); Hub hub = new DefaultHub(); @@ -94,27 +92,29 @@ public class DefaultProvider implements Provider { File file = configuration.persistence().file(container_profile_file_path); String id = null; - if (file.exists()){ + if (file.exists()) { log.info("loading persisted state for container"); - try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){ - id = (String)ois.readObject(); - }catch(Exception e){ - log.error("error loading persisted state, creating new uuid",e); + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + id = (String) ois.readObject(); + } catch (Exception e) { + log.error("error loading persisted state, creating new uuid", e); } - } - if (id==null){ + } + if (id == null) { id = UUID.randomUUID().toString(); - log.info("container id created is {}",id); + log.info("container id created is {}", id); - } + } - AuthorizationProviderFactory authfactory = configuration.getauthorizationConfiguration().getAuthProviderFactory(); + AuthorizationProviderFactory authfactory = configuration.getauthorizationConfiguration() + .getAuthProviderFactory(); Credentials credentials = configuration.getauthorizationConfiguration().getCredentials(); - + AuthorizationProvider authProvider = authfactory.connect(credentials); - - containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, new Properties()); + + containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, + new Properties()); } return containerContext; } @@ -127,12 +127,13 @@ public class DefaultProvider implements Provider { ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){ + if (currentClassLoader.getParent() != null + && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) { log.trace("probably i'm in a webapp classloader"); currentClassLoader = currentClassLoader.getParent(); } - List defaultHandlers = binder.bindHandlers(currentClassLoader); + List defaultHandlers = binder.bindHandlers(currentClassLoader); return defaultHandlers; @@ -150,34 +151,37 @@ public class DefaultProvider implements Provider { ApplicationConfiguration embedded = configurationFor(application); ApplicationConfiguration external = context.configuration().app(application.getContextPath()); - //shouldn't happen: management shouldn't have started at all - if (embedded==null && external==null) - throw new AssertionError("application @ "+application.getContextPath()+" is not distributed with " - + configuration_file_path+" and there is no external configuration for it in "+container_configuraton_file_path); + // shouldn't happen: management shouldn't have started at all + if (embedded == null && external == null) + throw new AssertionError("application @ " + application.getContextPath() + " is not distributed with " + + configuration_file_path + " and there is no external configuration for it in " + + container_configuraton_file_path); - //no embedded configuration + // no embedded configuration if (embedded == null) { - configuration = external ; + configuration = external; - log.info("loaded configuration for application "+configuration.name()+" from "+container_configuraton_file_path); - } - else { + log.info("loaded configuration for application " + configuration.name() + " from " + + container_configuraton_file_path); + } else { configuration = embedded; if (external == null) - log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path); + log.info("loaded configuration for application " + configuration.name() + " from " + + configuration_file_path); else { configuration.merge(external); - log.info("loaded configuration for application "+configuration.name()+" from "+configuration_file_path+" and "+container_configuraton_file_path); + log.info("loaded configuration for application " + configuration.name() + " from " + + configuration_file_path + " and " + container_configuraton_file_path); } - } + } ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration(context.configuration(), configuration); @@ -187,16 +191,16 @@ public class DefaultProvider implements Provider { ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, configuration.name()); File file = bridgedConfiguration.persistence().file(profile_file_path); - String id= null; - if (file.exists()){ + String id = null; + if (file.exists()) { log.info("loading persisted state for application {}", application.getContextPath()); - try(ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))){ - id = (String)ois.readObject(); - }catch(Exception e){ - log.error("error loading persisted state, creating new uuid",e); + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + id = (String) ois.readObject(); + } catch (Exception e) { + log.error("error loading persisted state, creating new uuid", e); } - } - if (id==null) + } + if (id == null) id = UUID.randomUUID().toString(); return new DefaultApplicationContext(id, context, application, bridgedConfiguration, hub, lifecycle, @@ -208,31 +212,29 @@ public class DefaultProvider implements Provider { try { - ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - - - //searching for smartegars related application handlers in the common classloader + // searching for smartegars related application handlers in the common + // classloader ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - if (currentClassLoader.getParent()!=null && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())){ + if (currentClassLoader.getParent() != null + && !currentClassLoader.getParent().equals(ClassLoader.getSystemClassLoader())) { log.trace("probably i'm in a webapp classloader"); currentClassLoader = currentClassLoader.getParent(); } ApplicationHandlers defaultHandlers = binder.bindHandlers(currentClassLoader); - return defaultHandlers; - + return defaultHandlers; } catch (RuntimeException e) { - throw new RuntimeException("cannot install handlers for application @ " + context.name()+" (see cause) ", e); + throw new RuntimeException("cannot install handlers for application @ " + context.name() + " (see cause) ", + e); } } - @Override public ApplicationExtensions extensionsFor(ApplicationContext context) { @@ -248,7 +250,8 @@ public class DefaultProvider implements Provider { config = getClass().getResourceAsStream(default_extensions_file_path); if (config == null) - throw new IllegalStateException("invalid distribution: cannot find " + default_extensions_file_path); + throw new IllegalStateException( + "invalid distribution: cannot find " + default_extensions_file_path); } else log.info("{} uses custom extensions @ {}", context.name(), extensions_file_path); @@ -259,12 +262,12 @@ public class DefaultProvider implements Provider { } catch (RuntimeException e) { - throw new RuntimeException("cannot install extensions for application @ " + context.name()+" (see cause) ", e); + throw new RuntimeException( + "cannot install extensions for application @ " + context.name() + " (see cause) ", e); } } - @Override public SmartGearsConfiguration smartgearsConfiguration() { @@ -297,7 +300,7 @@ public class DefaultProvider implements Provider { InputStream config = application.getResourceAsStream(configuration_file_path); - if (config == null) + if (config == null) return null; ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); @@ -313,7 +316,7 @@ public class DefaultProvider implements Provider { private ContainerConfiguration containerConfiguration() { - if (configFile==null) { + if (configFile == null) { String home = Utils.home(); @@ -324,22 +327,24 @@ public class DefaultProvider implements Provider { File homeDir = new File(home); if (!(homeDir.exists() && homeDir.isDirectory() && homeDir.canRead() && homeDir.canWrite())) - throw new IllegalStateException("invalid node configuration: home "+home+" does not exist or is not a directory or cannot be accessed in read/write mode"); - - configFile = new File(homeDir,container_configuraton_file_path); + throw new IllegalStateException("invalid node configuration: home " + home + + " does not exist or is not a directory or cannot be accessed in read/write mode"); + configFile = new File(homeDir, container_configuraton_file_path); log.trace("reading container configuration @ {} ", configFile.getAbsolutePath()); } if (!(configFile.exists() && configFile.canRead())) - throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" does not exist or cannot be accessed"); + throw new IllegalStateException("invalid node configuration: file " + configFile.getAbsolutePath() + + " does not exist or cannot be accessed"); ContainerConfiguration configuration; - try (InputStream stream = new FileInputStream(configFile)){ - configuration= new ContainerConfigurationBinder().load(stream); - }catch (Exception e) { - throw new IllegalStateException("invalid node configuration: file "+configFile.getAbsolutePath()+" is invalid", e); + try (InputStream stream = new FileInputStream(configFile)) { + configuration = new ContainerConfigurationBinder().load(stream); + } catch (Exception e) { + throw new IllegalStateException( + "invalid node configuration: file " + configFile.getAbsolutePath() + " is invalid", e); } return configuration; @@ -348,43 +353,56 @@ public class DefaultProvider implements Provider { @Override public synchronized List publishers() { if (this.publishers == null) { - //retrieve from root class loader - Collection urls = ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader()); - urls.removeIf(url -> url.toString().endsWith(".so") || url.toString().endsWith(".zip") ); + Set> annotatedPublishers; - ConfigurationBuilder reflectionConf = new ConfigurationBuilder().addUrls(urls).setScanners(new TypeAnnotationsScanner(), new SubTypesScanner()); + try (ScanResult result = new ClassGraph().enableClassInfo().enableAnnotationInfo() + .addClassLoader(Thread.currentThread().getContextClassLoader()).scan()) { - Reflections reflection = new Reflections(reflectionConf); + ClassInfoList classInfos = result.getClassesWithAnnotation(SmartgearsProfilePublisher.class.getName()); + + annotatedPublishers = classInfos.stream().map(ClassInfo::loadClass) + .filter(c -> Publisher.class.isAssignableFrom(c)).collect(Collectors.toSet()); + + } + /* + * Collection urls = + * ClasspathHelper.forClassLoader(Thread.currentThread().getContextClassLoader() + * ); urls.removeIf(url -> url.toString().endsWith(".so") || + * url.toString().endsWith(".zip") ); + * + * + * ConfigurationBuilder reflectionConf = new + * ConfigurationBuilder().addUrls(urls).setScanners(new + * TypeAnnotationsScanner(), new SubTypesScanner()); + * + * Reflections reflection = new Reflections(reflectionConf); + * + * = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class); + */ - Set> annotatedPublishers = reflection.getTypesAnnotatedWith(SmartgearsProfilePublisher.class); List foundPublishers = new ArrayList(); - for (Class annotatedPublisher: annotatedPublishers) { - if (Publisher.class.isAssignableFrom(annotatedPublisher)) - try { - foundPublishers.add((Publisher)annotatedPublisher.newInstance()); - log.info("added class {} to publishers",annotatedPublisher); - } catch (Exception e) { - log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(),e); - } - else - log.warn("publisher class {} discarded, it doesn't implements Publisher class", annotatedPublisher.getCanonicalName()); - + for (Class annotatedPublisher : annotatedPublishers) { + try { + foundPublishers.add((Publisher) annotatedPublisher.getDeclaredConstructor().newInstance()); + log.info("added class {} to publishers", annotatedPublisher); + } catch (Throwable e) { + log.error("publisher class {} cannot be instantiated", annotatedPublisher.getCanonicalName(), e); + } + } this.publishers = foundPublishers; if (foundPublishers.isEmpty()) log.warn("no publishers found in classloader"); } - + return this.publishers; } -/* - @Override - public AuthorizationProvider authorizationProvider() { - return containerContext.authorizationProvider(); - } -*/ - + /* + * @Override public AuthorizationProvider authorizationProvider() { return + * containerContext.authorizationProvider(); } + */ + } From b9f17e5a0b91b73f28a9988bc1f8f961d50a9eb1 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 1 Feb 2023 14:55:11 +0100 Subject: [PATCH 45/49] added check --- .../gcube/smartgears/extensions/resource/HealthResource.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java index ef18a62..cf12869 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -82,7 +82,8 @@ public class HealthResource extends ApiResource { } public void stop() { - timer.cancel(); + if (timer!=null) + timer.cancel(); } @Override From a76b823c49da9937c8e728d6285fa5f5d0179681 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 1 Feb 2023 14:56:57 +0100 Subject: [PATCH 46/49] update --- .../gcube/smartgears/extensions/resource/HealthResource.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java index cf12869..54e774b 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -39,6 +39,8 @@ public class HealthResource extends ApiResource { public static final String mapping = "/health"; + public static final String readiness_mapping = "/readiness"; + private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json)); private HealthManager manager; @@ -95,7 +97,7 @@ public class HealthResource extends ApiResource { String contextpath = req.getContextPath(); log.info("context path is {}", req.getContextPath()); - if (contextpath.endsWith("/readiness")) + if (contextpath.endsWith(readiness_mapping)) response = readiness(); else RequestError.resource_notfound_error.fire(); From e48f50e91b4f268199fc5b40f9913154f227fd16 Mon Sep 17 00:00:00 2001 From: lucio Date: Wed, 1 Feb 2023 17:18:13 +0100 Subject: [PATCH 47/49] added automatic metrics for micrometer --- .../java/org/gcube/smartgears/Bootstrap.java | 8 +- .../java/org/gcube/smartgears/Constants.java | 5 + .../ApplicationConfigurationBinder.java | 2 + .../DefaultApplicationContext.java | 1 - .../handlers/application/RequestHandler.java | 4 + .../lifecycle/ApplicationProfileManager.java | 5 +- .../request/RequestAccounting.java | 91 ++++++++++--------- .../application/request/RequestMetrics.java | 48 ++++++++++ .../smartgears/managers/RequestManager.java | 51 ++--------- 9 files changed, 126 insertions(+), 89 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java diff --git a/src/main/java/org/gcube/smartgears/Bootstrap.java b/src/main/java/org/gcube/smartgears/Bootstrap.java index f5df24a..ad52fd8 100644 --- a/src/main/java/org/gcube/smartgears/Bootstrap.java +++ b/src/main/java/org/gcube/smartgears/Bootstrap.java @@ -16,9 +16,11 @@ import org.slf4j.LoggerFactory; import io.micrometer.core.instrument.Metrics; import io.micrometer.core.instrument.binder.jvm.ClassLoaderMetrics; +import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; import io.micrometer.core.instrument.binder.system.ProcessorMetrics; +import io.micrometer.core.instrument.binder.system.UptimeMetrics; import io.micrometer.prometheus.PrometheusConfig; import io.micrometer.prometheus.PrometheusMeterRegistry; @@ -95,12 +97,14 @@ public class Bootstrap implements ServletContainerInitializer { context = ProviderFactory.provider().containerContext(); PrometheusMeterRegistry registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); - registry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + new ClassLoaderMetrics().bindTo(registry); new JvmMemoryMetrics().bindTo(registry); - //new JvmGcMetrics().bindTo(registry); + new JvmGcMetrics().bindTo(registry); new ProcessorMetrics().bindTo(registry); new JvmThreadMetrics().bindTo(registry); + new UptimeMetrics().bindTo(registry); + new ProcessorMetrics().bindTo(registry); Metrics.addRegistry(registry); diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index 3db496f..ea1e571 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -98,6 +98,11 @@ public class Constants { */ public static final String request_validation = "request-validation"; + /** + * The configuration name of {@link RequestMetrics}s. + */ + public static final String request_metrics = "request-metrics"; + /** * The configuration name of {@link RequestValidator}s. */ diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java index e12e04d..d31bf64 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -19,6 +19,7 @@ import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager; import org.gcube.smartgears.handlers.application.request.RequestAccounting; +import org.gcube.smartgears.handlers.application.request.RequestMetrics; import org.gcube.smartgears.handlers.application.request.RequestValidator; /** @@ -66,6 +67,7 @@ public class ApplicationConfigurationBinder { List requestHandlers = new LinkedList(); //ADDING BASE Handler (order is important) + requestHandlers.add(new RequestMetrics()); requestHandlers.add(new RequestValidator()); requestHandlers.add(new RequestAccounting()); diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 4e0b443..7aeeea8 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -6,7 +6,6 @@ import org.gcube.common.events.Hub; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; -import org.gcube.smartgears.health.HealthManager; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; diff --git a/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java b/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java index 07f83e2..95fa9d2 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/RequestHandler.java @@ -22,6 +22,10 @@ public abstract class RequestHandler extends AbstractHandler implements Applicat abstract public String getName(); + public boolean isUnfiltrable() { + return false; + } + /** * Initialises the handler. * diff --git a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java index 25d2cf1..8c9eafe 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/lifecycle/ApplicationProfileManager.java @@ -83,8 +83,9 @@ public class ApplicationProfileManager extends ApplicationLifecycleHandler { publishers = context.container().configuration().mode()!=Mode.offline? ProviderFactory.provider().publishers(): Collections.emptyList(); - registerObservers(); - schedulePeriodicUpdates(); + + registerObservers(); + schedulePeriodicUpdates(); } // helpers diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index a815151..c51990e 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -1,7 +1,5 @@ package org.gcube.smartgears.handlers.application.request; -import java.util.concurrent.TimeUnit; - import org.gcube.accounting.datamodel.UsageRecord.OperationResult; import org.gcube.accounting.datamodel.usagerecords.ServiceUsageRecord; import org.gcube.accounting.persistence.AccountingPersistence; @@ -17,13 +15,11 @@ import org.gcube.smartgears.utils.InnerMethodName; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import io.micrometer.core.instrument.Metrics; - public class RequestAccounting extends RequestHandler { private static Logger log = LoggerFactory.getLogger(RequestAccounting.class); - private static ThreadLocal startCallThreadLocal = new ThreadLocal(); + private static ThreadLocal startCallThreadLocal = new ThreadLocal(); private static final String UNKNOWN = "Unknown"; @@ -36,24 +32,24 @@ public class RequestAccounting extends RequestHandler { public void handleRequest(RequestEvent e) { ApplicationContext appContext = e.context(); - String context = getContext(appContext); - if (InnerMethodName.instance.get()==null) { + if (InnerMethodName.instance.get() == null) { String calledMethod = e.request().getRequestURI().substring(e.request().getContextPath().length()); if (calledMethod.isEmpty()) calledMethod = "/"; - calledMethod= e.request().getMethod()+" "+calledMethod; + calledMethod = e.request().getMethod() + " " + calledMethod; InnerMethodName.instance.set(calledMethod); } - String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): - UNKNOWN; + String caller = SecretManagerProvider.instance.get() != null + ? SecretManagerProvider.instance.get().getOwner().getId() + : UNKNOWN; startCallThreadLocal.set(System.currentTimeMillis()); - log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", - appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, e.request().getRemoteHost(), context ); + log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", appContext.configuration().name(), + appContext.configuration().serviceClass(), InnerMethodName.instance.get(), caller, + e.request().getRemoteHost(), context); } @@ -65,33 +61,41 @@ public class RequestAccounting extends RequestHandler { String context = getContext(appContext); - String caller = SecretManagerProvider.instance.get()!=null ? SecretManagerProvider.instance.get().getOwner().getId(): - UNKNOWN; + String caller = SecretManagerProvider.instance.get() != null + ? SecretManagerProvider.instance.get().getOwner().getId() + : UNKNOWN; String callerQualifier = UNKNOWN; - //retieves caller Ip when there is a proxy + // retieves caller Ip when there is a proxy String callerIp = e.request().getHeader("x-forwarded-for"); - if(callerIp==null) - callerIp=e.request().getRemoteHost(); + if (callerIp == null) + callerIp = e.request().getRemoteHost(); - boolean success = e.response().getStatus()<400; + boolean success = e.response().getStatus() < 400; - if (appContext.container().configuration().mode()!=Mode.offline) - generateAccounting(caller,callerQualifier,callerIp==null?UNKNOWN:callerIp , success, context, appContext); + if (appContext.container().configuration().mode() != Mode.offline) + generateAccounting(caller, callerQualifier, callerIp == null ? UNKNOWN : callerIp, success, context, + appContext); - long durationInMillis = System.currentTimeMillis()-startCallThreadLocal.get(); + long durationInMillis = System.currentTimeMillis() - startCallThreadLocal.get(); - Metrics.globalRegistry.timer("http.requests", "response",Integer.toString(e.response().getStatus()) - , "context", context, "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, - "caller-username", caller, "service-class", appContext.configuration().serviceClass(), "service-name", appContext.configuration().name(), - "method", InnerMethodName.instance.get()).record(durationInMillis, TimeUnit.MILLISECONDS); - - log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", - appContext.configuration().name(),appContext.configuration().serviceClass(), InnerMethodName.instance.get(), - caller, callerIp, context, success?"SUCCEDED":"FAILED", e.response().getStatus(),durationInMillis); + /* + * Metrics.globalRegistry.timer("smartgears.requests", + * "response",Integer.toString(e.response().getStatus()) , "context", context, + * "result", success?"SUCCEDED":"FAILED", "caller-ip", callerIp, + * "caller-username", caller, "service-class", + * appContext.configuration().serviceClass(), "service-name", + * appContext.configuration().name(), "method", + * InnerMethodName.instance.get()).record(durationInMillis, + * TimeUnit.MILLISECONDS); + */ + log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", + appContext.configuration().name(), appContext.configuration().serviceClass(), + InnerMethodName.instance.get(), caller, callerIp, context, success ? "SUCCEDED" : "FAILED", + e.response().getStatus(), durationInMillis); - }catch (Exception e1) { - log.error("error on accounting",e); + } catch (Exception e1) { + log.error("error on accounting", e); throw e1; } finally { startCallThreadLocal.remove(); @@ -100,11 +104,13 @@ public class RequestAccounting extends RequestHandler { } - void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, String gcubeContext, ApplicationContext appContext){ - AccountingPersistenceFactory.setFallbackLocation(appContext.container().configuration().accountingFallbackLocation()); + void generateAccounting(String caller, String callerQualifier, String remoteHost, boolean success, + String gcubeContext, ApplicationContext appContext) { + AccountingPersistenceFactory + .setFallbackLocation(appContext.container().configuration().accountingFallbackLocation()); AccountingPersistence persistence = AccountingPersistenceFactory.getPersistence(); ServiceUsageRecord serviceUsageRecord = new ServiceUsageRecord(); - try{ + try { serviceUsageRecord.setConsumerId(caller); serviceUsageRecord.setCallerQualifier(callerQualifier); @@ -112,21 +118,22 @@ public class RequestAccounting extends RequestHandler { serviceUsageRecord.setServiceClass(appContext.configuration().serviceClass()); serviceUsageRecord.setServiceName(appContext.configuration().name()); - serviceUsageRecord.setHost(appContext.container().configuration().hostname()+":"+appContext.container().configuration().port()); + serviceUsageRecord.setHost(appContext.container().configuration().hostname() + ":" + + appContext.container().configuration().port()); serviceUsageRecord.setCalledMethod(InnerMethodName.instance.get()); serviceUsageRecord.setCallerHost(remoteHost); - serviceUsageRecord.setOperationResult(success?OperationResult.SUCCESS:OperationResult.FAILED); - serviceUsageRecord.setDuration(System.currentTimeMillis()-startCallThreadLocal.get()); + serviceUsageRecord.setOperationResult(success ? OperationResult.SUCCESS : OperationResult.FAILED); + serviceUsageRecord.setDuration(System.currentTimeMillis() - startCallThreadLocal.get()); persistence.account(serviceUsageRecord); - }catch(Exception ex){ - log.warn("invalid record passed to accounting ",ex); + } catch (Exception ex) { + log.warn("invalid record passed to accounting ", ex); } } private String getContext(ApplicationContext appContext) { String infrastructure = appContext.container().configuration().infrastructure(); - String context= "/"+infrastructure; + String context = "/" + infrastructure; if (SecretManagerProvider.instance.get() != null) context = SecretManagerProvider.instance.get().getContext(); return context; @@ -137,6 +144,4 @@ public class RequestAccounting extends RequestHandler { return getName(); } - - } diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java new file mode 100644 index 0000000..719a173 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java @@ -0,0 +1,48 @@ +package org.gcube.smartgears.handlers.application.request; + +import java.time.Duration; + +import org.gcube.smartgears.Constants; +import org.gcube.smartgears.handlers.application.RequestEvent; +import org.gcube.smartgears.handlers.application.RequestHandler; +import org.gcube.smartgears.handlers.application.ResponseEvent; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import io.micrometer.core.instrument.Metrics; + +public class RequestMetrics extends RequestHandler { + + private static Logger log = LoggerFactory.getLogger(RequestMetrics.class); + + private static ThreadLocal startCallThreadLocal = new ThreadLocal(); + + private static final String HTTP_REQUEST_METRICS_NAME = "http.server.requests"; + + @Override + public String getName() { + return Constants.request_metrics; + } + + @Override + public boolean isUnfiltrable() { + return true; + } + + @Override + public void handleRequest(RequestEvent e) { + startCallThreadLocal.set(System.currentTimeMillis()); + } + + @Override + public void handleResponse(ResponseEvent e) { + String statusCode = Integer.toString(e.response().getStatus()); + Metrics.globalRegistry.timer(HTTP_REQUEST_METRICS_NAME, "status", statusCode).record(Duration.ofMillis(System.currentTimeMillis() - startCallThreadLocal.get())); + Metrics.globalRegistry.counter(HTTP_REQUEST_METRICS_NAME, "status", statusCode); + startCallThreadLocal.remove(); + log.debug("metrics for current call saved"); + } + + + +} diff --git a/src/main/java/org/gcube/smartgears/managers/RequestManager.java b/src/main/java/org/gcube/smartgears/managers/RequestManager.java index 11cf66c..d1f2dec 100644 --- a/src/main/java/org/gcube/smartgears/managers/RequestManager.java +++ b/src/main/java/org/gcube/smartgears/managers/RequestManager.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.stream.Collectors; import javax.servlet.Filter; import javax.servlet.FilterChain; @@ -139,19 +140,18 @@ public class RequestManager implements Filter { for (Exclude exclude : context.configuration().excludes()){ String excludePath= exclude.getPath(); log.trace("exclude is {}",exclude); - if ( - (WILDCARD).equals(excludePath) || + if ((WILDCARD).equals(excludePath) || (excludePath.endsWith(WILDCARD) && path!=null && path.startsWith(excludePath.substring(0,excludePath.length()-2))) || excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1))) ){ - //ALL handler are filtered - if (exclude.getHandlers().isEmpty()) return Collections.emptyList(); + //ALL handler are filtered except for unfiltrable + if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream().filter(RequestHandler::isUnfiltrable).toList(); List filteredHandlers = new ArrayList<>(); - for (RequestHandler rh : handlersToFilter){ - if (!exclude.getHandlers().contains(rh.getName())) + for (RequestHandler rh : handlersToFilter) + if (rh.isUnfiltrable() || !exclude.getHandlers().contains(rh.getName())) filteredHandlers.add(rh); - } + return filteredHandlers; } } @@ -168,10 +168,10 @@ public class RequestManager implements Filter { if (include.getHandlers().isEmpty()) return handlersToFilter; List filteredHandlers = new ArrayList<>(); - for (RequestHandler rh : handlersToFilter){ - if (include.getHandlers().contains(rh.getName())) + for (RequestHandler rh : handlersToFilter) + if (rh.isUnfiltrable() || include.getHandlers().contains(rh.getName())) filteredHandlers.add(rh); - } + return filteredHandlers; } } @@ -213,37 +213,6 @@ public class RequestManager implements Filter { } - // helpers - /* - private boolean shouldExcludeRequest(HttpServletRequest request) { - - String query = request.getQueryString(); - - log.debug("servletPath is {} and pathInfo is {}",request.getServletPath(), request.getPathInfo()); - - if ("wsdl".equals(query) || "wsdl=1".equals(query)) - return true; - - String path = request.getServletPath()==null?"":request.getServletPath(); - - path += request.getPathInfo() ==null?"":request.getPathInfo(); - - - log.debug("check if should exclude call with path {}", path); - - for (Exclude exclude : context.configuration().excludes()){ - if (!exclude.getHandlers().isEmpty()) continue; - String excludePath= exclude.getPath(); - log.trace("exclude is {}",exclude); - if ( - (EXCLUDE_ALL).equals(exclude) || - (excludePath.endsWith(EXCLUDE_ALL) && path!=null && path.startsWith(excludePath.substring(0,excludePath.length()-2))) || - excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1))) - ) - return true; - } - return false; - }*/ private void handleError(HttpServletRequest request, HttpServletResponse response,Throwable t) throws IOException { From 766238c8e3183d0c611e667591dd30e67e142d01 Mon Sep 17 00:00:00 2001 From: lucio Date: Mon, 6 Feb 2023 17:34:18 +0100 Subject: [PATCH 48/49] removed all JAXB dependencies --- pom.xml | 16 +- .../java/org/gcube/smartgears/Bootstrap.java | 1 + .../java/org/gcube/smartgears/Constants.java | 28 +- .../configuration/ComponentConfiguration.java | 10 + .../configuration/Configurable.java | 6 + .../configuration/ConfiguredWith.java | 14 + .../PersistenceConfiguration.java | 37 +++ .../application/ApplicationConfiguration.java | 278 ++++++++++-------- .../ApplicationConfigurationBinder.java | 40 +-- .../application/ApplicationExtensions.java | 75 ----- .../BridgedApplicationConfiguration.java | 149 ---------- .../DefaultApplicationConfiguration.java | 207 ------------- .../{Exclude.java => GCubeExclude.java} | 22 +- .../{Include.java => GCubeInclude.java} | 22 +- .../container/ContainerConfiguration.java | 16 +- .../ContainerConfigurationBinder.java | 128 ++++---- .../library/SmartGearsConfiguration.java | 6 +- .../SmartGearsConfigurationBinder.java | 47 --- .../DefaultApplicationContext.java | 56 +++- .../context/container/ContainerContext.java | 3 +- .../container/DefaultContainerContext.java | 56 +++- .../smartgears/extensions/ApiResource.java | 6 +- .../extensions/ApplicationExtension.java | 4 +- .../smartgears/extensions/HttpController.java | 26 +- .../smartgears/extensions/HttpExtension.java | 15 +- .../resource/ConfigurationResource.java | 3 +- .../resource/FrontPageResource.java | 3 +- .../resource/LifecycleResource.java | 4 - .../extensions/resource/RemoteResource.java | 3 - .../application/request/RequestValidator.java | 12 +- .../managers/ApplicationManager.java | 26 +- .../smartgears/managers/ContainerManager.java | 2 +- .../smartgears/managers/RequestManager.java | 11 +- ...LocalPersistence.java => LocalWriter.java} | 28 +- .../persistence/LocalWriterConfiguration.java | 24 ++ .../persistence/PersistenceWriter.java | 6 +- .../smartgears/provider/DefaultProvider.java | 152 +--------- .../gcube/smartgears/provider/Provider.java | 13 +- .../DefaultAuthorizationProvider.java | 4 +- .../resources/META-INF/default-extensions.xml | 4 - src/main/resources/META-INF/profile.xml | 29 -- src/test/java/utils/ConfigurationTest.java | 88 ++++++ .../java/utils/PersistenceWriterTest.java | 6 + src/test/java/utils/TestProvider.java | 14 +- src/test/java/utils/TestUtils.java | 155 ---------- src/test/resources/application.yaml | 18 ++ 46 files changed, 692 insertions(+), 1181 deletions(-) create mode 100644 src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java create mode 100644 src/main/java/org/gcube/smartgears/configuration/Configurable.java create mode 100644 src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java create mode 100644 src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java delete mode 100644 src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java delete mode 100644 src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java delete mode 100644 src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java rename src/main/java/org/gcube/smartgears/configuration/application/{Exclude.java => GCubeExclude.java} (68%) rename src/main/java/org/gcube/smartgears/configuration/application/{Include.java => GCubeInclude.java} (69%) delete mode 100644 src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java rename src/main/java/org/gcube/smartgears/persistence/{LocalPersistence.java => LocalWriter.java} (65%) create mode 100644 src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java delete mode 100644 src/main/resources/META-INF/default-extensions.xml delete mode 100644 src/main/resources/META-INF/profile.xml create mode 100644 src/test/java/utils/ConfigurationTest.java delete mode 100644 src/test/java/utils/TestUtils.java create mode 100644 src/test/resources/application.yaml diff --git a/pom.xml b/pom.xml index 7320a92..a0bc221 100644 --- a/pom.xml +++ b/pom.xml @@ -37,6 +37,16 @@ https://code-repo.d4science.org/gCubeSystem/common-smartgears + + org.reflections + reflections + 0.9.10 + + + org.yaml + snakeyaml + 1.21 + io.github.classgraph classgraph @@ -106,12 +116,6 @@ 4.0.1 provided - - - javax.xml.bind - jaxb-api - - io.micrometer diff --git a/src/main/java/org/gcube/smartgears/Bootstrap.java b/src/main/java/org/gcube/smartgears/Bootstrap.java index ad52fd8..f1fa17f 100644 --- a/src/main/java/org/gcube/smartgears/Bootstrap.java +++ b/src/main/java/org/gcube/smartgears/Bootstrap.java @@ -86,6 +86,7 @@ public class Bootstrap implements ServletContainerInitializer { } // helpers + @SuppressWarnings("resource") private void initialiseContainer() { try { diff --git a/src/main/java/org/gcube/smartgears/Constants.java b/src/main/java/org/gcube/smartgears/Constants.java index ea1e571..e2df6f2 100644 --- a/src/main/java/org/gcube/smartgears/Constants.java +++ b/src/main/java/org/gcube/smartgears/Constants.java @@ -27,7 +27,7 @@ public class Constants { /** * The container configuration file path, relative to the container configuration directory. - */ + */ public static final String container_configuraton_file_path = "container.ini"; @@ -36,19 +36,15 @@ public class Constants { */ public static final String container_profile_file_path = "ghn.xml"; + /* public static final String container_profile_file_path_copy = "ghn.xml.copy"; - - - /** - * The library configuration resource path. - */ - public static final String library_configuration_file_path = "/META-INF/smartgears-config.xml"; + */ /** * The name of the context property that contains the node profile. - */ + public static final String container_profile_property = "ghn-profile"; - + */ /** * The default value of for the container publication frequency. @@ -59,7 +55,7 @@ public class Constants { /** * The application configuration resource path. */ - public static final String configuration_file_path = "/WEB-INF/gcube-app.xml"; + public static final String configuration_file_path = "/WEB-INF/application.yaml"; /** @@ -73,16 +69,6 @@ public class Constants { */ public static final String root_mapping = "/gcube/resource"; - /** - * The application extensions configuration resource path. - */ - public static final String extensions_file_path = "/WEB-INF/gcube-extensions.xml"; - - /** - * The default application extensions configuration resource path. - */ - public static final String default_extensions_file_path = "/META-INF/default-extensions.xml"; - /** * The application frontpage resource path. */ @@ -126,8 +112,6 @@ public class Constants { public static final String remote_management = "remote-management"; - - /** * The path of the application profile file, relative to the service configuration directory. */ diff --git a/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java new file mode 100644 index 0000000..6c5f9da --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/ComponentConfiguration.java @@ -0,0 +1,10 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo; +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import org.gcube.com.fasterxml.jackson.annotation.JsonTypeInfo.Id; + +@JsonTypeInfo(include=As.PROPERTY, use=Id.CLASS, property= "className") +public interface ComponentConfiguration { + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/Configurable.java b/src/main/java/org/gcube/smartgears/configuration/Configurable.java new file mode 100644 index 0000000..9bfcb3c --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/Configurable.java @@ -0,0 +1,6 @@ +package org.gcube.smartgears.configuration; + +public interface Configurable { + + void configure(ComponentConfiguration configuration); +} diff --git a/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java b/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java new file mode 100644 index 0000000..be55a56 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/ConfiguredWith.java @@ -0,0 +1,14 @@ +package org.gcube.smartgears.configuration; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target(ElementType.TYPE) +public @interface ConfiguredWith { + + public Class value(); +} diff --git a/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java new file mode 100644 index 0000000..3e42147 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/PersistenceConfiguration.java @@ -0,0 +1,37 @@ +package org.gcube.smartgears.configuration; + +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; +import org.gcube.common.validator.annotations.IsValid; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.persistence.PersistenceWriter; + +@JsonInclude(value = Include.NON_NULL) +@JsonAutoDetect(fieldVisibility = Visibility.ANY) +public class PersistenceConfiguration { + + @NotNull + private Class implementationClass; + + @IsValid + private ComponentConfiguration writerConfiguration; + + protected PersistenceConfiguration() {} + + public PersistenceConfiguration(Class implementationClass, T writerConfiguration) { + super(); + this.implementationClass = implementationClass; + this.writerConfiguration = writerConfiguration; + } + + public Class getImplementationClass() { + return this.implementationClass; + } + + public ComponentConfiguration getWriterConfiguration() { + return writerConfiguration; + } + +} diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index 6b2a9ec..c8624da 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -1,140 +1,182 @@ package org.gcube.smartgears.configuration.application; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; import java.util.Set; -import org.gcube.smartgears.configuration.ProxyAddress; -import org.gcube.smartgears.persistence.PersistenceWriter; +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect; +import org.gcube.com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import org.gcube.com.fasterxml.jackson.annotation.JsonIgnore; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude; +import org.gcube.com.fasterxml.jackson.annotation.JsonInclude.Include; +import org.gcube.com.fasterxml.jackson.annotation.JsonProperty; +import org.gcube.common.validator.ValidationError; +import org.gcube.common.validator.Validator; +import org.gcube.common.validator.ValidatorFactory; +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.PersistenceConfiguration; /** - * The configuration of the application. - * - * @author Fabio Simeoni + * The configuration of a managed app. + *

+ * Includes the list of its client services. + * + * @author Lucio Lelii * */ -public interface ApplicationConfiguration { +@JsonInclude(value = Include.NON_NULL) +@JsonAutoDetect(fieldVisibility = Visibility.ANY) +public class ApplicationConfiguration { + @NotNull + String name; + + @NotNull + String group; + + @NotNull + String version; + + String description=""; + + @JsonIgnore + String context; + + private boolean proxable = true; - /** - * Returns the context path of the application - * @return the context path - */ - String context(); + Set excludes= null; - boolean proxable(); + Set includes= null; - ProxyAddress proxyAddress(); + @NotEmpty @JsonProperty("persistence") + PersistenceConfiguration persistenceConfiguration; - ApplicationConfiguration proxyAddress(ProxyAddress proxy); + public Set excludes() { + return excludes; + } - /** - * Sets the context path of the application - * @param context the context path - * @return this configuration - */ - ApplicationConfiguration context(String context); + public Set includes() { + return includes; + } + public ApplicationConfiguration() {} + + public String name() { + return name; + } + + public String context() { + return context; + } + + public ApplicationConfiguration excludes(GCubeExclude ... excludes) { + this.excludes=new HashSet(Arrays.asList(excludes)); + return this; + } + + public ApplicationConfiguration includes(GCubeInclude... includes) { + this.includes=new HashSet(Arrays.asList(includes)); + return this; + } + + public ApplicationConfiguration context(String context) { + this.context = context; + return this; + } + + public ApplicationConfiguration name(String name) { + this.name=name; + return this; + } + + public ApplicationConfiguration persistenceConfiguration(PersistenceConfiguration configuration) { + this.persistenceConfiguration = configuration; + return this; + } + + public ApplicationConfiguration proxable(boolean proxable) { + this.proxable = proxable; + return this; + } + + public String serviceClass() { + return group; + } + + + public ApplicationConfiguration serviceClass(String group) { + this.group=group; + return this; + } + + public String version() { + return version; + } + + public ApplicationConfiguration version(String version) { + this.version=version; + return this; + } + + + public String description() { + return description; + } + + public ApplicationConfiguration description(String description) { + this.description=description; + return this; + } + + public boolean proxable() { + return proxable; + } - /** - * Returns the name of the application. - * @return the name - */ - String name(); - - - /** - * Sets the name of the application. - * @param name the name - * @return this configuration - */ - ApplicationConfiguration name(String name); + public PersistenceConfiguration persistenceConfiguration() { + return persistenceConfiguration; + } + + public void validate() { + + List msgs = new ArrayList(); + + Validator validator = ValidatorFactory.validator(); + + for (ValidationError error : validator.validate(this)) + msgs.add(error.toString()); + + if (!this.excludes().isEmpty() && !this.includes().isEmpty()) + msgs.add("exclude tags and includes tags are mutually exclusive"); + + if (!msgs.isEmpty()) + throw new IllegalStateException("invalid configuration: "+msgs); + + } - /** - * Returns the class of the application - * @return the class - */ - String serviceClass(); + @Override + public int hashCode() { + return Objects.hash(description, excludes, group, includes, name, proxable, version); + } - /** - * Sets the class of the application. - * @param serviceClass the class - * @return this configuration - */ - ApplicationConfiguration serviceClass(String serviceClass); - - /** - * Returns the version of the application. - * @return the version - */ - String version(); - - /** - * Sets the version of the application. - * @param version the version - * @return this configuration - */ - ApplicationConfiguration version(String version); - - /** - * Returns the description of the application. - * @return the description - */ - String description(); - - /** - * Sets the description of the application. - * @param description the description - * @return this configuration - */ - ApplicationConfiguration description(String description); + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + ApplicationConfiguration other = (ApplicationConfiguration) obj; + return Objects.equals(description, other.description) + && Objects.equals(excludes, other.excludes) && Objects.equals(group, other.group) + && Objects.equals(includes, other.includes) && Objects.equals(name, other.name) + && proxable == other.proxable && Objects.equals(version, other.version); + } - /** - * Returns the persistence manager of the application. - * @return the manager - */ - PersistenceWriter persistence(); - - - /** - * Returns a set of request paths that should not be subjected to request management. - * @return the set of exclude paths. - */ - Set excludes(); - - /** - * Returns a set of request paths that should be subjected to request management. - * @return the set of exclude paths. - */ - Set includes(); - - - /** - * Sets the persistence manager of the application. - * @param manager the manager - * @return this configuration - */ - ApplicationConfiguration persistence(PersistenceWriter manager); - - - /** - * Validates this configuration. - * - * @throws IllegalStateException if the configuration is not valid - */ - void validate(); - - - /** - * Merges this configuration with another configuration - * @param config the other configuration - */ - void merge(ApplicationConfiguration config); - - ApplicationConfiguration excludes(Exclude ... excludes); - - ApplicationConfiguration includes(Include ... includes); - - - } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java index d31bf64..144d57a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -1,26 +1,17 @@ package org.gcube.smartgears.configuration.application; -import static org.gcube.smartgears.utils.Utils.closeSafely; -import static org.gcube.smartgears.utils.Utils.unchecked; - import java.io.InputStream; -import java.lang.reflect.Modifier; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.ServiceLoader; -import java.util.Set; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -import org.gcube.smartgears.extensions.ApplicationExtension; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager; import org.gcube.smartgears.handlers.application.request.RequestAccounting; import org.gcube.smartgears.handlers.application.request.RequestMetrics; import org.gcube.smartgears.handlers.application.request.RequestValidator; +import org.yaml.snakeyaml.Yaml; /** * Binds {@link ApplicationConfiguration}s to and from XML serialisations. @@ -37,21 +28,15 @@ public class ApplicationConfigurationBinder { * @return the configuration * @throws RuntimeException if the serialisation is invalid */ - public ApplicationConfiguration bind(InputStream stream) { - + public ApplicationConfiguration load(InputStream stream) { try { - - JAXBContext ctx = JAXBContext.newInstance(DefaultApplicationConfiguration.class); - - return (ApplicationConfiguration) ctx.createUnmarshaller().unmarshal(stream); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid service configuration", e); - - } - finally { - closeSafely(stream); + Yaml yaml = new Yaml(); + ObjectMapper mapper = new ObjectMapper(); + String mapAsString = mapper.writeValueAsString(yaml.load(stream)); + + return mapper.readValue(mapAsString, ApplicationConfiguration.class); + }catch (Exception e) { + throw new RuntimeException(e); } } @@ -92,7 +77,7 @@ public class ApplicationConfigurationBinder { * @param stream the serialisation * @return the extensions * @throws RuntimeException if the serialisation is invalid - */ + public ApplicationExtensions bindExtensions(InputStream stream) { //collects handler classes @@ -136,7 +121,8 @@ public class ApplicationConfigurationBinder { return scanned; } - + */ + public void scanForApplicationHandlers(ClassLoader currentClassLoader) { // TODO Auto-generated method stub } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java deleted file mode 100644 index 53496de..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationExtensions.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.gcube.smartgears.configuration.application; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import javax.xml.bind.Unmarshaller; -import javax.xml.bind.annotation.XmlAnyElement; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.validator.ValidationError; -import org.gcube.common.validator.Validator; -import org.gcube.common.validator.ValidatorFactory; -import org.gcube.common.validator.annotations.IsValid; -import org.gcube.smartgears.extensions.ApplicationExtension; -import org.w3c.dom.Element; - -/** - * The {@link ApplicationExtension}s that manage the application. - * - * @author Fabio Simeoni - * - */ -@XmlRootElement(name="extensions") -public class ApplicationExtensions { - - @XmlAnyElement(lax=true) @IsValid - List extensions = new ArrayList(); - - public ApplicationExtensions() {} - - /** - * Returns the extensions for the application. - * @return the extensions - */ - public List extensions() { - return extensions; - } - - /** - * Sets the extensions for the application. - * @param extensions the extensions - * @return this configuration - */ - public ApplicationExtensions set(ApplicationExtension ... extensions) { - this.extensions = Arrays.asList(extensions); - return this; - } - - @Override - public String toString() { - return extensions.toString(); - } - - public void validate() { - - List msgs = new ArrayList(); - - Validator validator = ValidatorFactory.validator(); - - for (ValidationError error : validator.validate(this)) - msgs.add(error.toString()); - - if (!msgs.isEmpty()) - throw new IllegalStateException("invalid configuration: "+msgs); - - } - - //since we use @AnyElement, after deserialisation, we check there are no DOM elements - void afterUnmarshal(Unmarshaller u, Object parent) { - for (Object o : extensions) - if (o instanceof Element) - throw new RuntimeException("invalid extensions detected: "+Element.class.cast(o).getLocalName()); - } - -} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java deleted file mode 100644 index 8028765..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/BridgedApplicationConfiguration.java +++ /dev/null @@ -1,149 +0,0 @@ -package org.gcube.smartgears.configuration.application; - -import java.io.File; -import java.util.Set; - -import org.gcube.smartgears.configuration.ProxyAddress; -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.gcube.smartgears.persistence.PersistenceWriter; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * - * @author Fabio Simeoni - * @author Luca Frosini (ISTI - CNR) - */ -public class BridgedApplicationConfiguration implements ApplicationConfiguration { - - private static Logger log = LoggerFactory.getLogger(ApplicationConfiguration.class); - - private final ApplicationConfiguration application; - - - public BridgedApplicationConfiguration(ContainerConfiguration container, ApplicationConfiguration config) { - - this.application=config; - - if (application.persistence()==null) { - - String location = container.persistence().getLocation()+"/"+application.name(); - File dir = new File(location); - if (!dir.exists()) - dir.mkdirs(); - - application.persistence(new LocalPersistence(location)); - - log.trace("setting persistence location for {} @ {}",application.name(), dir.getAbsolutePath()); - - } - - if (application.proxable() && container.proxy()!=null) - application.proxyAddress(container.proxy()); - - } - - public ApplicationConfiguration inner() { - return application; - } - - @Override - public String context() { - return application.context(); - } - - @Override - public ApplicationConfiguration context(String context) { - return application.context(context); - } - - public String name() { - return application.name(); - } - - public ApplicationConfiguration name(String name) { - return application.name(name); - } - - public String serviceClass() { - return application.serviceClass(); - } - - public ApplicationConfiguration serviceClass(String group) { - return application.serviceClass(group); - } - - public String version() { - return application.version(); - } - - public ApplicationConfiguration version(String version) { - return application.version(version); - } - - public String description() { - return application.description(); - } - - public ApplicationConfiguration description(String description) { - return application.description(description); - } - - public PersistenceWriter persistence() { - return application.persistence(); - } - - public ApplicationConfiguration persistence(PersistenceWriter manager) { - return application.persistence(manager); - } - - - public void validate() { - - application.validate(); - - } - - @Override - public Set excludes() { - return application.excludes(); - } - - @Override - public Set includes() { - return application.includes(); - } - - @Override - public void merge(ApplicationConfiguration config) { - application.merge(config); - } - - - @Override - public boolean proxable() { - return application.proxable(); - } - - @Override - public ApplicationConfiguration excludes(Exclude ... excludes) { - return application.excludes(excludes); - } - - @Override - public ApplicationConfiguration includes(Include... includes) { - return application.includes(includes); - } - - @Override - public ProxyAddress proxyAddress() { - return application.proxyAddress(); - } - - @Override - public ApplicationConfiguration proxyAddress(ProxyAddress proxy) { - return proxyAddress(proxy); - } - -} diff --git a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java deleted file mode 100644 index 94248e6..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/application/DefaultApplicationConfiguration.java +++ /dev/null @@ -1,207 +0,0 @@ -package org.gcube.smartgears.configuration.application; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlElement; -import javax.xml.bind.annotation.XmlElementRef; -import javax.xml.bind.annotation.XmlRootElement; - -import org.gcube.common.validator.ValidationError; -import org.gcube.common.validator.Validator; -import org.gcube.common.validator.ValidatorFactory; -import org.gcube.common.validator.annotations.IsValid; -import org.gcube.common.validator.annotations.NotNull; -import org.gcube.smartgears.configuration.ProxyAddress; -import org.gcube.smartgears.persistence.LocalPersistence; -import org.gcube.smartgears.persistence.PersistenceWriter; - -/** - * The configuration of a managed app. - *

- * Includes the list of its client services. - * - * @author Fabio Simeoni - * @author Luca Frosini (ISTI - CNR) - * - */ -@XmlRootElement(name="application") -public class DefaultApplicationConfiguration implements ApplicationConfiguration { - - String context; - - @XmlAttribute(name = "proxable") - private boolean proxable = true; - - @XmlElement(name="name" , required=true) - @NotNull - String name; - - @XmlElement(name="group", required=true) - @NotNull - String group; - - @XmlElement(name="version", required=true) - @NotNull - String version; - - @XmlElement(name="description") - String description=""; - - @XmlElementRef - Set excludes= new LinkedHashSet(); - - @XmlElementRef - Set includes= new LinkedHashSet(); - - @XmlElementRef(type=LocalPersistence.class) - @NotNull @IsValid - private PersistenceWriter persistenceManager; - - @IsValid - ProxyAddress proxyAddress; - - @Override - public Set excludes() { - return excludes; - } - - - @Override - public Set includes() { - return includes; - } - - public DefaultApplicationConfiguration() {} - - @Override - public String name() { - return name; - } - - @Override - public String context() { - return context; - } - - @Override - public ApplicationConfiguration context(String context) { - this.context=context; - return this; - } - - @Override - public ApplicationConfiguration excludes(Exclude ... excludes) { - this.excludes=new HashSet(Arrays.asList(excludes)); - return this; - } - - @Override - public ApplicationConfiguration includes(Include... includes) { - this.includes=new HashSet(Arrays.asList(includes)); - return this; - } - - @Override - public ApplicationConfiguration name(String name) { - this.name=name; - return this; - } - - @Override - public String serviceClass() { - return group; - } - - - @Override - public ApplicationConfiguration serviceClass(String group) { - this.group=group; - return this; - } - - @Override - public String version() { - return version; - } - - @Override - public ApplicationConfiguration version(String version) { - this.version=version; - return this; - } - - - @Override - public String description() { - return description; - } - - @Override - public ApplicationConfiguration description(String description) { - this.description=description; - return this; - } - - @Override - public boolean proxable() { - return proxable; - } - - public ProxyAddress proxyAddress() { - return proxyAddress; - } - - - public ApplicationConfiguration proxyAddress(ProxyAddress proxyAddress) { - this.proxyAddress = proxyAddress; - return this; - } - - - @Override - public PersistenceWriter persistence() { - return persistenceManager; - } - - @Override - public ApplicationConfiguration persistence(PersistenceWriter manager) { - this.persistenceManager=manager; - return this; - } - - @Override - public void validate() { - - List msgs = new ArrayList(); - - Validator validator = ValidatorFactory.validator(); - - for (ValidationError error : validator.validate(this)) - msgs.add(error.toString()); - - if (!this.excludes().isEmpty() && !this.includes().isEmpty()) - msgs.add("exclude tags and includes tags are mutually exclusive"); - - if (!msgs.isEmpty()) - throw new IllegalStateException("invalid configuration: "+msgs); - - } - - - @Override - public void merge(ApplicationConfiguration config) { - - if (config.persistence()!=null) - persistence(config.persistence()); - - } - - - -} \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/configuration/application/Exclude.java b/src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java similarity index 68% rename from src/main/java/org/gcube/smartgears/configuration/application/Exclude.java rename to src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java index 579758b..264500b 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/Exclude.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/GCubeExclude.java @@ -3,20 +3,14 @@ package org.gcube.smartgears.configuration.application; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; +import org.gcube.common.validator.annotations.NotEmpty; -@XmlRootElement(name="exclude") -@XmlAccessorType(XmlAccessType.FIELD) -public class Exclude { +public class GCubeExclude { - @XmlAttribute(name="handlers") + @NotEmpty private List handlers = new ArrayList(); - @XmlValue + @NotEmpty private String path; public List getHandlers() { @@ -27,14 +21,14 @@ public class Exclude { return path; } - protected Exclude() {} + protected GCubeExclude() {} - public Exclude(String path) { + public GCubeExclude(String path) { super(); this.path = path; } - public Exclude(List handlers, String path) { + public GCubeExclude(List handlers, String path) { super(); this.handlers = handlers; this.path = path; @@ -57,7 +51,7 @@ public class Exclude { return false; if (getClass() != obj.getClass()) return false; - Exclude other = (Exclude) obj; + GCubeExclude other = (GCubeExclude) obj; if (handlers == null) { if (other.handlers != null) return false; diff --git a/src/main/java/org/gcube/smartgears/configuration/application/Include.java b/src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java similarity index 69% rename from src/main/java/org/gcube/smartgears/configuration/application/Include.java rename to src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java index e8486c7..8991456 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/Include.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/GCubeInclude.java @@ -3,20 +3,14 @@ package org.gcube.smartgears.configuration.application; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; +import org.gcube.common.validator.annotations.NotEmpty; -@XmlRootElement(name="include") -@XmlAccessorType(XmlAccessType.FIELD) -public class Include { +public class GCubeInclude { - @XmlAttribute(name="handlers") + @NotEmpty private List handlers = new ArrayList(); - @XmlValue + @NotEmpty private String path; public List getHandlers() { @@ -27,14 +21,14 @@ public class Include { return path; } - protected Include() {} + protected GCubeInclude() {} - public Include(String path) { + public GCubeInclude(String path) { super(); this.path = path; } - public Include(List handlers, String path) { + public GCubeInclude(List handlers, String path) { super(); this.handlers = handlers; this.path = path; @@ -57,7 +51,7 @@ public class Include { return false; if (getClass() != obj.getClass()) return false; - Include other = (Include) obj; + GCubeInclude other = (GCubeInclude) obj; if (handlers == null) { if (other.handlers != null) return false; diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java index 0fef04c..128b968 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfiguration.java @@ -14,9 +14,9 @@ import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.common.validator.annotations.NotNull; import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration; import org.gcube.smartgears.configuration.Mode; +import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.persistence.PersistenceWriter; /** * The configuration of the container. @@ -46,7 +46,7 @@ public class ContainerConfiguration { @NotNull @IsValid - private PersistenceWriter persistenceManager; + private PersistenceConfiguration persistenceConfiguration; @NotNull @IsValid private AuthorizationProviderConfiguration authorizationConfiguration; @@ -72,8 +72,8 @@ public class ContainerConfiguration { this.accountingFallbackLocation = accountingFallbackLocation; } - protected void setPersistenceManager(PersistenceWriter persistenceManager) { - this.persistenceManager = persistenceManager; + protected void setPersistenceConfiguration(PersistenceConfiguration persistenceConfiguration) { + this.persistenceConfiguration = persistenceConfiguration; } protected void setAuthorizationProviderConfiguration( @@ -195,8 +195,8 @@ public class ContainerConfiguration { * Returns the persistence manager of the container. * @return the manager */ - public PersistenceWriter persistence() { - return persistenceManager; + public PersistenceConfiguration persistenceConfiguration() { + return this.persistenceConfiguration; } /** @@ -211,7 +211,7 @@ public class ContainerConfiguration { * Returns the authorization configuration. * @return AuthorizationProviderConfiguration the configuration */ - public AuthorizationProviderConfiguration getauthorizationConfiguration() { + public AuthorizationProviderConfiguration authorizationConfiguration() { return authorizationConfiguration; } @@ -254,7 +254,7 @@ public class ContainerConfiguration { public String toString() { return "ContainerConfiguration [baseConfiguration=" + baseConfiguration + ", properties=" + properties + ", site=" + site + ", proxy=" + proxy + ", accountingFallbackLocation=" + accountingFallbackLocation - + ", persistenceManager=" + persistenceManager.getClass().getSimpleName() + + ", persistence=" + persistenceConfiguration.getImplementationClass().getSimpleName() + ", authorizationProvider=" + authorizationConfiguration + "]"; } diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 599d605..686aba5 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -10,11 +10,15 @@ import java.util.stream.Collectors; import org.gcube.common.security.credentials.Credentials; import org.gcube.smartgears.configuration.AuthorizationProviderConfiguration; +import org.gcube.smartgears.configuration.ComponentConfiguration; +import org.gcube.smartgears.configuration.ConfiguredWith; +import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.ProxyAddress; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager; -import org.gcube.smartgears.persistence.LocalPersistence; +import org.gcube.smartgears.persistence.LocalWriter; +import org.gcube.smartgears.persistence.LocalWriterConfiguration; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProviderFactory; import org.gcube.smartgears.security.defaults.DefaultAuthorizationProviderFactory; @@ -30,120 +34,138 @@ import org.ini4j.Profile.Section; */ public class ContainerConfigurationBinder { - public ContainerConfiguration load(InputStream stream) { try { Ini configurator = new Ini(stream); ContainerConfiguration conf = new ContainerConfiguration(); Section nodeSection = configurator.get("node"); - if (nodeSection != null ) { + if (nodeSection != null) { BaseConfiguration nodeConf = new BaseConfiguration(); nodeSection.to(nodeConf); conf.setBaseConfiguration(nodeConf); } Section propertiesSection = configurator.get("properties"); - if (propertiesSection!=null) + if (propertiesSection != null) conf.setProperties(propertiesSection.entrySet().stream() - .collect(Collectors.toMap(Entry::getKey, Entry::getValue))); + .collect(Collectors.toMap(Entry::getKey, Entry::getValue))); Section siteSection = configurator.get("site"); if (siteSection != null) { Site siteConf = new Site(); siteSection.to(siteConf); - conf.setSite(siteConf); + conf.setSite(siteConf); } initAuthorizationPart(configurator, conf); - + initPersistencePart(configurator, conf); - + initProxyPart(configurator, conf); - - //TODO: find a solution for this shit - String location = Utils.home()+"/state"; + // TODO: find a solution for this shit + String location = Utils.home() + "/state"; File dir = new File(location); if (!dir.exists()) dir.mkdirs(); conf.setAccountingFallbackLocation(location); // END Shit - + return conf; - }catch (Exception e) { + } catch (Exception e) { throw new RuntimeException(e); } } - private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + private void initProxyPart(Ini configurator, ContainerConfiguration conf) throws Exception { Section proxySection = configurator.get("proxy"); if (proxySection != null) { ProxyAddress proxyConf = new ProxyAddress(); proxySection.to(proxyConf); - conf.setProxy(proxyConf); + conf.setProxy(proxyConf); } } - - private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception{ + + @SuppressWarnings("unchecked") + private void initPersistencePart(Ini configurator, ContainerConfiguration conf) throws Exception { Section persistenceSection = configurator.get("persistence"); if (persistenceSection != null) { String type = persistenceSection.get("class"); - if (type ==null) + if (type == null) throw new Exception("ini file error: type not found in \"persistence\" section"); - PersistenceWriter persistenceWriter; + /* + * PersistenceWriter persistenceWriter; try { Object persistenceImpl = + * Class.forName(type).getDeclaredConstructor().newInstance(); persistenceWriter + * = PersistenceWriter.class.cast(persistenceImpl); }catch (Exception e) { throw + * new + * Exception("ini file error: invalid persistence type in \"persistence\" section" + * , e); } + */ + // persistenceSection.to(persistenceWriter); + + Class persistenceClass = null; try { - Object persistenceImpl = Class.forName(type).newInstance(); - persistenceWriter = PersistenceWriter.class.cast(persistenceImpl); - }catch (Exception e) { + persistenceClass = (Class) Class.forName(type); + } catch (Exception e) { throw new Exception("ini file error: invalid persistence type in \"persistence\" section", e); } - persistenceSection.to(persistenceWriter); - conf.setPersistenceManager(persistenceWriter); + if (!persistenceClass.isAnnotationPresent(ConfiguredWith.class)) + throw new Exception( + "ini file error: invalid class type in \"persistence\" section,ConfiguredWith annotation not present"); + Class writerConfClass = persistenceClass + .getAnnotation(ConfiguredWith.class).value(); + ComponentConfiguration writerConfiguration = writerConfClass.getDeclaredConstructor().newInstance(); + persistenceSection.to(writerConfiguration, "."); + conf.setPersistenceConfiguration( + new PersistenceConfiguration((Class) persistenceClass, writerConfiguration)); } else { - String location = Utils.home()+"/state"; + String location = Utils.home() + "/state"; File dir = new File(location); if (!dir.exists()) dir.mkdirs(); - conf.setPersistenceManager(new LocalPersistence(location)); + + conf.setPersistenceConfiguration( + new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location))); } + } - - private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception{ + + private void initAuthorizationPart(Ini configurator, ContainerConfiguration conf) throws Exception { Section authorizationSection = configurator.get("authorization"); if (authorizationSection != null) { - + String provider = authorizationSection.get("factory"); AuthorizationProviderFactory authProviderFactory; - if (provider!=null) { + if (provider != null) { try { - Object authProviderImpl = Class.forName(provider).newInstance(); + Object authProviderImpl = Class.forName(provider).getDeclaredConstructor().newInstance(); authProviderFactory = AuthorizationProviderFactory.class.cast(authProviderImpl); - }catch (Exception e) { + } catch (Exception e) { throw new Exception("ini file error: invalid provider type in \"authorization\" section", e); } - } else + } else authProviderFactory = new DefaultAuthorizationProviderFactory(); - + authorizationSection.to(authProviderFactory, "factory."); - - + String type = authorizationSection.get("credentials.class"); - if (type ==null) + if (type == null) throw new Exception("ini file error: credentials type not found in \"authorization\" section"); Credentials credentials; try { - Object credentialsImpl = Class.forName(type).newInstance(); + Object credentialsImpl = Class.forName(type).getDeclaredConstructor().newInstance(); credentials = Credentials.class.cast(credentialsImpl); - }catch (Exception e) { + } catch (Exception e) { throw new Exception("ini file error: invalid credentials type in \"authorization\" section", e); } authorizationSection.to(credentials, "credentials."); - - conf.setAuthorizationProviderConfiguration(new AuthorizationProviderConfiguration(authProviderFactory, credentials)); + + conf.setAuthorizationProviderConfiguration( + new AuthorizationProviderConfiguration(authProviderFactory, credentials)); } } - + /** * Returns the handlers of the container from their XML serialisation. * @@ -154,24 +176,22 @@ public class ContainerConfigurationBinder { public List bindHandlers(ClassLoader classloader) { LinkedList handlers = new LinkedList(); - - //ADDING BASE Handlers (order is important) + + // ADDING BASE Handlers (order is important) handlers.add(new AccountingManager()); handlers.add(new ContainerProfileManager()); - + handlers.addAll(scanForContainerHadlers(classloader)); - + return handlers; - + } - - - + private List scanForContainerHadlers(ClassLoader classloader) throws RuntimeException { - - //TODO: scan for Container Handler - + + // TODO: scan for Container Handler + return Collections.emptyList(); } - + } diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java index 1541837..f628c6a 100644 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java @@ -3,18 +3,14 @@ package org.gcube.smartgears.configuration.library; import java.util.ArrayList; import java.util.List; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.common.validator.ValidationError; import org.gcube.common.validator.Validator; import org.gcube.common.validator.ValidatorFactory; import org.gcube.common.validator.annotations.NotEmpty; -@XmlRootElement(name="smartgears") public class SmartGearsConfiguration { - @XmlAttribute @NotEmpty + @NotEmpty private String version; public SmartGearsConfiguration(){ diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java deleted file mode 100644 index 11a9b42..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfigurationBinder.java +++ /dev/null @@ -1,47 +0,0 @@ -package org.gcube.smartgears.configuration.library; - -import java.io.InputStream; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -import org.gcube.smartgears.configuration.container.ContainerConfiguration; -import org.gcube.smartgears.utils.Utils; - -/** - * Binds {@link ContainerConfiguration}s to and from XML serialisations. - * - * @author Fabio Simeoni - * - */ -public class SmartGearsConfigurationBinder { - - /** - * Returns a {@link ContainerConfiguration} from its XML serialisation. - * - * @param stream the serialisation - * @return the configuration - * @throws RuntimeException if the serialisation is invalid - */ - public SmartGearsConfiguration bind(InputStream stream) { - - try { - - JAXBContext ctx = JAXBContext.newInstance(SmartGearsConfiguration.class); - - SmartGearsConfiguration config = (SmartGearsConfiguration) ctx.createUnmarshaller().unmarshal(stream); - - return config; - - } catch (JAXBException e) { - - throw new RuntimeException("invalid library configuration", e); - - } - finally { - - Utils.closeSafely(stream); - } - } - -} diff --git a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java index 7aeeea8..5cf5735 100644 --- a/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java +++ b/src/main/java/org/gcube/smartgears/context/application/DefaultApplicationContext.java @@ -1,14 +1,24 @@ package org.gcube.smartgears.context.application; +import static org.gcube.smartgears.Constants.profile_file_path; + +import java.io.File; +import java.io.FileInputStream; +import java.io.ObjectInputStream; +import java.util.UUID; + import javax.servlet.ServletContext; import org.gcube.common.events.Hub; +import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Default {@link ApplicationContext} implementation. @@ -18,12 +28,15 @@ import org.gcube.smartgears.security.AuthorizationProvider; */ public class DefaultApplicationContext implements ApplicationContext { + private static Logger log = LoggerFactory.getLogger(DefaultApplicationContext.class); + private final ContainerContext container; private final ServletContext sctx; private final ApplicationConfiguration configuration; private final ApplicationLifecycle lifecycle; private final Properties properties; private final Hub hub; + private final PersistenceWriter persistenceWriter; private final String id; /** @@ -35,7 +48,30 @@ public class DefaultApplicationContext implements ApplicationContext { * @param lifecycle the lifecycle * @param properties the properties */ - public DefaultApplicationContext(String id,ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) { + public DefaultApplicationContext(ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) { + + PersistenceConfiguration persistenceWriterConf = configuration.persistenceConfiguration(); + + try { + persistenceWriter = persistenceWriterConf.getImplementationClass().getDeclaredConstructor().newInstance(); + persistenceWriter.configure(persistenceWriterConf.getWriterConfiguration()); + }catch (Exception e) { + throw new RuntimeException(e); + } + + File file = persistenceWriter.file(profile_file_path); + String id = null; + if (file.exists()) { + log.info("loading persisted state for application {}", sctx.getContextPath()); + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + id = (String) ois.readObject(); + } catch (Exception e) { + log.error("error loading persisted state, creating new uuid", e); + } + } + if (id == null) + id = UUID.randomUUID().toString(); + this.id = id; this.container=container; this.sctx = sctx; @@ -50,9 +86,21 @@ public class DefaultApplicationContext implements ApplicationContext { * @param context the other instance */ public DefaultApplicationContext(ApplicationContext context) { - this(context.id(), context.container(),context.application(),context.configuration(),context.events(), context.lifecycle(), new Properties(context.properties())); + this(context.id(), context.persistence(), context.container(),context.application(),context.configuration(),context.events(), context.lifecycle(), new Properties(context.properties())); } + private DefaultApplicationContext(String id, PersistenceWriter writer, ContainerContext container,ServletContext sctx,ApplicationConfiguration configuration, Hub hub, ApplicationLifecycle lifecycle, Properties properties) { + this.id = id; + this.container=container; + this.sctx = sctx; + this.configuration=configuration; + this.hub=hub; + this.lifecycle = lifecycle; + this.properties=properties; + this.persistenceWriter = writer; + + } + @Override public ServletContext application() { return sctx; @@ -85,10 +133,8 @@ public class DefaultApplicationContext implements ApplicationContext { @Override public PersistenceWriter persistence() { - return configuration.persistence(); + return persistenceWriter; } - - @Override public Properties properties() { diff --git a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java index 454a94a..e3729a9 100644 --- a/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/ContainerContext.java @@ -39,7 +39,7 @@ public interface ContainerContext { * Returns the persistence manager of the container. * @return the manager */ - PersistenceWriter persistence(); + PersistenceWriter persistenceWriter(); /** * Returns the properties of the container. @@ -51,5 +51,6 @@ public interface ContainerContext { AuthorizationProvider authorizationProvider(); + } diff --git a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java index 0cf4ad4..cde9c96 100644 --- a/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java +++ b/src/main/java/org/gcube/smartgears/context/container/DefaultContainerContext.java @@ -1,14 +1,21 @@ package org.gcube.smartgears.context.container; -import static org.gcube.smartgears.Constants.container_profile_property; +import static org.gcube.smartgears.Constants.container_profile_file_path; + +import java.io.File; +import java.io.FileInputStream; +import java.io.ObjectInputStream; +import java.util.UUID; import org.gcube.common.events.Hub; -import org.gcube.common.resources.gcore.HostingNode; +import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; import org.gcube.smartgears.persistence.PersistenceWriter; import org.gcube.smartgears.security.AuthorizationProvider; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Default {@link ContainerContext} implementation. @@ -18,12 +25,15 @@ import org.gcube.smartgears.security.AuthorizationProvider; */ public class DefaultContainerContext implements ContainerContext { + private static Logger log = LoggerFactory.getLogger(DefaultContainerContext.class); + private final ContainerConfiguration configuration; private final ContainerLifecycle lifecycle; private final Properties properties; private final Hub hub; private final AuthorizationProvider authorizationProvider; private final String id; + private final PersistenceWriter persistenceWriter; /** * Creates an instance with mandatory parameters. * @param configuration the configuration @@ -31,19 +41,49 @@ public class DefaultContainerContext implements ContainerContext { * @param lifecycle the lifecycle * @param properties the properties */ - public DefaultContainerContext(String id,ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle, AuthorizationProvider authProvider, + public DefaultContainerContext(ContainerConfiguration configuration, Hub hub, ContainerLifecycle lifecycle, AuthorizationProvider authProvider, Properties properties) { - this.id = id; this.configuration=configuration; this.hub=hub; this.lifecycle = lifecycle; this.properties=properties; this.authorizationProvider = authProvider; - } + + PersistenceConfiguration persistenceWriterConf = configuration.persistenceConfiguration(); + + try { + persistenceWriter = persistenceWriterConf.getImplementationClass().getDeclaredConstructor().newInstance(); + persistenceWriter.configure(persistenceWriterConf.getWriterConfiguration()); + }catch (Exception e) { + throw new RuntimeException(e); + } + + File file = persistenceWriter.file(container_profile_file_path); + String id = null; + if (file.exists()) { + log.info("loading persisted state for container"); + try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { + id = (String) ois.readObject(); + } catch (Exception e) { + log.error("error loading persisted state, creating new uuid", e); + } + + } + if (id == null) { + id = UUID.randomUUID().toString(); + log.info("container id created is {}", id); + + } + + this.id = id; + + } + + /* public HostingNode profile() { return properties().lookup(container_profile_property).value(HostingNode.class); - }; + };*/ @Override public ContainerConfiguration configuration() { @@ -61,8 +101,8 @@ public class DefaultContainerContext implements ContainerContext { } @Override - public PersistenceWriter persistence() { - return configuration.persistence(); + public PersistenceWriter persistenceWriter() { + return persistenceWriter; } @Override diff --git a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java index a49eb27..1be961e 100644 --- a/src/main/java/org/gcube/smartgears/extensions/ApiResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/ApiResource.java @@ -9,7 +9,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.gcube.smartgears.Constants; -import org.gcube.smartgears.configuration.application.Exclude; +import org.gcube.smartgears.configuration.application.GCubeExclude; /** * A resource-specifc API handled by an {@link HttpController}. @@ -53,8 +53,8 @@ public abstract class ApiResource extends HttpExtension { } @Override - public Set excludes() { - return Collections.singleton(new Exclude(Constants.root_mapping+mapping())); + public Set excludes() { + return Collections.singleton(new GCubeExclude(Constants.root_mapping+mapping())); } /** diff --git a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java index 9658b4d..0d130d1 100644 --- a/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/ApplicationExtension.java @@ -4,7 +4,7 @@ import java.util.Set; import javax.servlet.Servlet; -import org.gcube.smartgears.configuration.application.Exclude; +import org.gcube.smartgears.configuration.application.GCubeExclude; import org.gcube.smartgears.context.application.ApplicationContext; /** @@ -41,5 +41,5 @@ public interface ApplicationExtension extends Servlet { * Returns the set of request paths that should be excluded from request management. * @return the set of request paths that should be excluded from request management */ - Set excludes(); + Set excludes(); } diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpController.java b/src/main/java/org/gcube/smartgears/extensions/HttpController.java index 4c78aa0..c9f6437 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpController.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpController.java @@ -1,8 +1,13 @@ package org.gcube.smartgears.extensions; -import static org.gcube.smartgears.Constants.*; -import static org.gcube.smartgears.handlers.application.request.RequestError.*; -import static org.gcube.smartgears.utils.Utils.*; +import static org.gcube.smartgears.Constants.accept; +import static org.gcube.smartgears.Constants.allow; +import static org.gcube.smartgears.Constants.content_type; +import static org.gcube.smartgears.handlers.application.request.RequestError.incoming_contenttype_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.method_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.outgoing_contenttype_unsupported_error; +import static org.gcube.smartgears.handlers.application.request.RequestError.resource_notfound_error; +import static org.gcube.smartgears.utils.Utils.notNull; import java.io.IOException; import java.util.Collection; @@ -17,7 +22,7 @@ import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.smartgears.configuration.application.Exclude; +import org.gcube.smartgears.configuration.application.GCubeExclude; import org.gcube.smartgears.context.application.ApplicationContext; /** @@ -69,9 +74,18 @@ public class HttpController extends HttpExtension { } @Override - public Set excludes() { + public void stop(){ + super.stop(); + for (ApiResource resource : resources.values()) + resource.stop(); - Set resourceExcludes = new LinkedHashSet(); + } + + + @Override + public Set excludes() { + + Set resourceExcludes = new LinkedHashSet(); for (ApiResource resource : resources.values()) resourceExcludes.addAll(resource.excludes()); diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java index f3660d2..0b76baf 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java @@ -1,17 +1,16 @@ package org.gcube.smartgears.extensions; -import static org.gcube.common.events.impl.Utils.*; +import static org.gcube.common.events.impl.Utils.valid; import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpServlet; -import javax.xml.bind.annotation.XmlAttribute; +import javax.ws.rs.HttpMethod; import org.gcube.common.validator.annotations.NotEmpty; -import org.gcube.smartgears.configuration.application.Exclude; +import org.gcube.smartgears.configuration.application.GCubeExclude; import org.gcube.smartgears.context.application.ApplicationContext; -import javax.ws.rs.HttpMethod; /** * An {@link ApplicationExtension} that implements the {@link HttpServlet} interface * @@ -48,10 +47,10 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx } } - @XmlAttribute @NotEmpty + @NotEmpty private String name; - @XmlAttribute @NotEmpty + @NotEmpty private String mapping; private ApplicationContext context; @@ -80,8 +79,8 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx public void stop() {} @Override - public Set excludes() { - return new HashSet(); //all managed by default + public Set excludes() { + return new HashSet(); //all managed by default } protected ApplicationContext context() { diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java index 0e3c939..534b46a 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java @@ -11,7 +11,6 @@ import javax.servlet.http.HttpServletResponse; import org.gcube.common.resources.gcore.Resources; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; @@ -37,7 +36,7 @@ public class ConfigurationResource extends ApiResource { @Override public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { - ApplicationConfiguration config = BridgedApplicationConfiguration.class.cast(context().configuration()).inner(); + ApplicationConfiguration config = context().configuration(); Resources.marshal(config,resp.getWriter()); } diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index fdbd49c..e038b33 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -4,7 +4,6 @@ import static org.gcube.smartgears.Constants.application_xhtml; import static org.gcube.smartgears.Constants.frontpage_file_path; import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; import static org.gcube.smartgears.handlers.application.request.RequestError.application_error; -import static org.gcube.smartgears.provider.ProviderFactory.provider; import static org.gcube.smartgears.utils.Utils.closeSafely; import java.io.BufferedReader; @@ -93,7 +92,7 @@ public class FrontPageResource extends ApiResource { values.put("status", context().lifecycle().state().toString()); - values.put("smartgears-version", provider().smartgearsConfiguration().version()); + //values.put("smartgears-version", provider().smartgearsConfiguration().version()); return values; } diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java index 072ca7f..7532484 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/LifecycleResource.java @@ -11,8 +11,6 @@ import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.bind.annotation.XmlRootElement; -import javax.xml.bind.annotation.XmlValue; import org.gcube.common.resources.gcore.Resources; import org.gcube.smartgears.extensions.ApiResource; @@ -86,10 +84,8 @@ public class LifecycleResource extends ApiResource { // helper classes - @XmlRootElement(name="state") public static class State { - @XmlValue public String value; State() { diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java index f160cae..e3fe3f2 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/RemoteResource.java @@ -2,8 +2,6 @@ package org.gcube.smartgears.extensions.resource; import static org.gcube.smartgears.Constants.remote_management; -import javax.xml.bind.annotation.XmlRootElement; - import org.gcube.smartgears.Constants; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.HttpController; @@ -14,7 +12,6 @@ import org.gcube.smartgears.extensions.HttpController; * @author Fabio Simeoni * */ -@XmlRootElement(name = remote_management) public class RemoteResource extends HttpController { private static final String default_mapping = Constants.root_mapping+"/*"; diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java index 1ec7266..571d71b 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestValidator.java @@ -13,9 +13,9 @@ import org.gcube.common.keycloak.KeycloakClientFactory; import org.gcube.common.security.ContextBean; import org.gcube.common.security.ContextBean.Type; import org.gcube.common.security.providers.SecretManagerProvider; -import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.GCubeSecret; import org.gcube.common.security.secrets.Secret; +import org.gcube.common.security.secrets.UmaTokenSecret; import org.gcube.smartgears.Constants; import org.gcube.smartgears.configuration.Mode; import org.gcube.smartgears.configuration.container.ContainerConfiguration; @@ -132,18 +132,18 @@ public class RequestValidator extends RequestHandler { log.info("d4s-user set to {} ", call.request().getHeader("d4s-user")); - String accessToken = null; + String umaToken = null; if (authHeader!=null && !authHeader.isEmpty()) if (authHeader.startsWith(BEARER_AUTH_PREFIX)) - accessToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); + umaToken = authHeader.substring(BEARER_AUTH_PREFIX.length()).trim(); Secret secret = null; - if (accessToken!=null) { - secret = new AccessTokenSecret(accessToken); + if (umaToken!=null) { + secret = new UmaTokenSecret(umaToken); SimpleCredentials credentials = (SimpleCredentials)appContext.authorizationProvider().getCredentials(); KeycloakClient client = KeycloakClientFactory.newInstance(); try { - if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), accessToken)) + if(!client.isAccessTokenVerified(secret.getContext(), credentials.getClientID(), credentials.getSecret(), umaToken)) RequestError.request_not_authorized_error.fire("access token verification error"); }catch (KeycloakClientException e) { RequestError.internal_server_error.fire("error contacting keycloak client", e); diff --git a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java index a1fbe26..3232aa5 100644 --- a/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ApplicationManager.java @@ -13,7 +13,6 @@ import java.io.File; import java.io.FileOutputStream; import java.io.ObjectOutputStream; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Map.Entry; @@ -24,7 +23,6 @@ import javax.servlet.ServletContextListener; import javax.servlet.ServletRegistration; import org.gcube.common.events.Observes; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; @@ -53,7 +51,7 @@ public class ApplicationManager { private ApplicationContext context; - private ApplicationExtensions extensions; + private List extensions; /** * Starts application management. @@ -83,9 +81,11 @@ public class ApplicationManager { ApplicationHandlers handlers = provider().handlersFor(context); + /* extensions = provider().extensionsFor(context); extensions.validate(); - + */ + List lifecycleHandlers = handlers.lifecycleHandlers(); List requestHandlers = handlers.requestHandlers(); @@ -94,11 +94,12 @@ public class ApplicationManager { log.trace("managing {} requests with {}", context.name(), requestHandlers); log.trace("extending {} API with {}", context.name(), extensions); + extensions = provider().extensionsFor(context); // order is important here: first add APIs - register(extensions); + registerExtension(extensions); // then intercept them all - register(requestHandlers); + registerHandlers(requestHandlers); // start lifecycle management start(lifecycleHandlers); @@ -127,7 +128,7 @@ public class ApplicationManager { } private void saveApplicationState() { - File file = context.configuration().persistence().file(profile_file_path); + File file = context.persistence().file(profile_file_path); try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){ oos.writeObject(context.id()); }catch (Exception e) { @@ -170,7 +171,7 @@ public class ApplicationManager { } - private void register(List rqHandlers) { + private void registerHandlers(List rqHandlers) { ServletContext app = context.application(); @@ -197,11 +198,11 @@ public class ApplicationManager { } } - private void register(ApplicationExtensions extensions) { + private void registerExtension(List extensions) { ServletContext application = context.application(); - for (ApplicationExtension extension : extensions.extensions()) + for (ApplicationExtension extension : extensions) try { @@ -234,10 +235,9 @@ public class ApplicationManager { } - private void unregister(ApplicationExtensions extensions) { - - for (ApplicationExtension extension : extensions.extensions()) + private void unregister(List extensions) { + for (ApplicationExtension extension : extensions) extension.stop(); } diff --git a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java index 5db0195..8bf1e50 100644 --- a/src/main/java/org/gcube/smartgears/managers/ContainerManager.java +++ b/src/main/java/org/gcube/smartgears/managers/ContainerManager.java @@ -86,7 +86,7 @@ public class ContainerManager { private void saveContainerState() { - File file = context.configuration().persistence().file(container_profile_file_path); + File file = context.persistenceWriter().file(container_profile_file_path); try(ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream(file))){ oos.writeObject(context.id()); }catch (Exception e) { diff --git a/src/main/java/org/gcube/smartgears/managers/RequestManager.java b/src/main/java/org/gcube/smartgears/managers/RequestManager.java index d1f2dec..cf28d8b 100644 --- a/src/main/java/org/gcube/smartgears/managers/RequestManager.java +++ b/src/main/java/org/gcube/smartgears/managers/RequestManager.java @@ -20,8 +20,8 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.gcube.common.authorization.library.exception.AuthorizationException; -import org.gcube.smartgears.configuration.application.Exclude; -import org.gcube.smartgears.configuration.application.Include; +import org.gcube.smartgears.configuration.application.GCubeExclude; +import org.gcube.smartgears.configuration.application.GCubeInclude; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.DefaultApplicationContext; import org.gcube.smartgears.handlers.application.ApplicationPipeline; @@ -137,7 +137,7 @@ public class RequestManager implements Filter { log.debug("check wich handler should be excluded {}", path); if (!context.configuration().excludes().isEmpty()) { - for (Exclude exclude : context.configuration().excludes()){ + for (GCubeExclude exclude : context.configuration().excludes()){ String excludePath= exclude.getPath(); log.trace("exclude is {}",exclude); if ((WILDCARD).equals(excludePath) || @@ -145,7 +145,8 @@ public class RequestManager implements Filter { excludePath.equals(path) || (path.endsWith("/") && excludePath.equals(path.substring(0, path.length()-1))) ){ //ALL handler are filtered except for unfiltrable - if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream().filter(RequestHandler::isUnfiltrable).toList(); + if (exclude.getHandlers().isEmpty()) return handlersToFilter.stream() + .filter(RequestHandler::isUnfiltrable).collect(Collectors.toList()); List filteredHandlers = new ArrayList<>(); for (RequestHandler rh : handlersToFilter) @@ -156,7 +157,7 @@ public class RequestManager implements Filter { } } } else if (!context.configuration().includes().isEmpty()) { - for (Include include : context.configuration().includes()){ + for (GCubeInclude include : context.configuration().includes()){ String includePath= include.getPath(); log.trace("include is {}",include); if ( diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java similarity index 65% rename from src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java rename to src/main/java/org/gcube/smartgears/persistence/LocalWriter.java index 49a9026..08a3327 100644 --- a/src/main/java/org/gcube/smartgears/persistence/LocalPersistence.java +++ b/src/main/java/org/gcube/smartgears/persistence/LocalWriter.java @@ -1,6 +1,5 @@ package org.gcube.smartgears.persistence; - import static org.gcube.smartgears.utils.Utils.fileAt; import static org.gcube.smartgears.utils.Utils.notNull; @@ -8,32 +7,21 @@ import java.io.File; import java.nio.file.Files; import java.nio.file.Paths; -import javax.xml.bind.annotation.XmlAccessType; -import javax.xml.bind.annotation.XmlAccessorType; -import javax.xml.bind.annotation.XmlAttribute; -import javax.xml.bind.annotation.XmlRootElement; +import org.gcube.smartgears.configuration.ComponentConfiguration; +import org.gcube.smartgears.configuration.ConfiguredWith; -import org.gcube.common.validator.annotations.NotEmpty; -import org.gcube.common.validator.annotations.NotNull; +@ConfiguredWith(LocalWriterConfiguration.class) +public class LocalWriter implements PersistenceWriter { -@XmlRootElement(name="persistence") -@XmlAccessorType(XmlAccessType.FIELD) -public class LocalPersistence implements PersistenceWriter { - - @XmlAttribute(name="location") @NotNull @NotEmpty private String location; - protected LocalPersistence() {} - - public LocalPersistence(String location) { + @Override + public void configure(ComponentConfiguration configuration) { + this.location = ((LocalWriterConfiguration) configuration).getLocation(); - notNull("persistence location",location); - - this.location=location; - - validate(); } + public String getLocation() { return location; } diff --git a/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java b/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java new file mode 100644 index 0000000..41d0f14 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/persistence/LocalWriterConfiguration.java @@ -0,0 +1,24 @@ +package org.gcube.smartgears.persistence; + +import org.gcube.common.validator.annotations.NotEmpty; +import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.ComponentConfiguration; + +public class LocalWriterConfiguration implements ComponentConfiguration{ + + @NotEmpty @NotNull + private String location; + + protected LocalWriterConfiguration() {} + + public LocalWriterConfiguration(String location) { + super(); + this.location = location; + } + + public String getLocation() { + return location; + } + + +} diff --git a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java index 6bbb144..b79e21a 100644 --- a/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java +++ b/src/main/java/org/gcube/smartgears/persistence/PersistenceWriter.java @@ -2,8 +2,10 @@ package org.gcube.smartgears.persistence; import java.io.File; -public interface PersistenceWriter { - +import org.gcube.smartgears.configuration.Configurable; + +public interface PersistenceWriter extends Configurable{ + File file(String path); File writefile(String path); diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 1cf05c0..8b72b56 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -2,22 +2,15 @@ package org.gcube.smartgears.provider; import static org.gcube.smartgears.Constants.configuration_file_path; import static org.gcube.smartgears.Constants.container_configuraton_file_path; -import static org.gcube.smartgears.Constants.container_profile_file_path; -import static org.gcube.smartgears.Constants.default_extensions_file_path; -import static org.gcube.smartgears.Constants.extensions_file_path; import static org.gcube.smartgears.Constants.ghn_home_env; import static org.gcube.smartgears.Constants.ghn_home_property; -import static org.gcube.smartgears.Constants.library_configuration_file_path; -import static org.gcube.smartgears.Constants.profile_file_path; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; -import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.List; import java.util.Set; -import java.util.UUID; import java.util.stream.Collectors; import javax.servlet.ServletContext; @@ -27,18 +20,16 @@ import org.gcube.common.events.impl.DefaultHub; import org.gcube.common.security.credentials.Credentials; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.application.BridgedApplicationConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfiguration; import org.gcube.smartgears.configuration.container.ContainerConfigurationBinder; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; -import org.gcube.smartgears.configuration.library.SmartGearsConfigurationBinder; import org.gcube.smartgears.context.Properties; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.application.DefaultApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; import org.gcube.smartgears.context.container.DefaultContainerContext; +import org.gcube.smartgears.extensions.ApplicationExtension; +import org.gcube.smartgears.extensions.resource.RemoteResource; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; @@ -88,32 +79,14 @@ public class DefaultProvider implements Provider { Hub hub = new DefaultHub(); ContainerLifecycle lifecycle = new ContainerLifecycle(hub); - - File file = configuration.persistence().file(container_profile_file_path); - - String id = null; - if (file.exists()) { - log.info("loading persisted state for container"); - try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { - id = (String) ois.readObject(); - } catch (Exception e) { - log.error("error loading persisted state, creating new uuid", e); - } - - } - if (id == null) { - id = UUID.randomUUID().toString(); - log.info("container id created is {}", id); - - } - - AuthorizationProviderFactory authfactory = configuration.getauthorizationConfiguration() + + AuthorizationProviderFactory authfactory = configuration.authorizationConfiguration() .getAuthProviderFactory(); - Credentials credentials = configuration.getauthorizationConfiguration().getCredentials(); + Credentials credentials = configuration.authorizationConfiguration().getCredentials(); AuthorizationProvider authProvider = authfactory.connect(credentials); - containerContext = new DefaultContainerContext(id, configuration, hub, lifecycle, authProvider, + containerContext = new DefaultContainerContext(configuration, hub, lifecycle, authProvider, new Properties()); } return containerContext; @@ -147,63 +120,20 @@ public class DefaultProvider implements Provider { @Override public ApplicationContext contextFor(ContainerContext context, ServletContext application) { - ApplicationConfiguration configuration = null; ApplicationConfiguration embedded = configurationFor(application); - ApplicationConfiguration external = context.configuration().app(application.getContextPath()); - + // shouldn't happen: management shouldn't have started at all - if (embedded == null && external == null) + if (embedded == null) throw new AssertionError("application @ " + application.getContextPath() + " is not distributed with " + configuration_file_path + " and there is no external configuration for it in " + container_configuraton_file_path); - // no embedded configuration - if (embedded == null) { - - configuration = external; - - log.info("loaded configuration for application " + configuration.name() + " from " - + container_configuraton_file_path); - } else { - - configuration = embedded; - - if (external == null) - - log.info("loaded configuration for application " + configuration.name() + " from " - + configuration_file_path); - - else { - - configuration.merge(external); - - log.info("loaded configuration for application " + configuration.name() + " from " - + configuration_file_path + " and " + container_configuraton_file_path); - - } - } - - ApplicationConfiguration bridgedConfiguration = new BridgedApplicationConfiguration(context.configuration(), - configuration); - + Hub hub = new DefaultHub(); - ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, configuration.name()); + ApplicationLifecycle lifecycle = new ApplicationLifecycle(hub, embedded.name()); - File file = bridgedConfiguration.persistence().file(profile_file_path); - String id = null; - if (file.exists()) { - log.info("loading persisted state for application {}", application.getContextPath()); - try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) { - id = (String) ois.readObject(); - } catch (Exception e) { - log.error("error loading persisted state, creating new uuid", e); - } - } - if (id == null) - id = UUID.randomUUID().toString(); - - return new DefaultApplicationContext(id, context, application, bridgedConfiguration, hub, lifecycle, + return new DefaultApplicationContext(context, application, embedded, hub, lifecycle, new Properties()); } @@ -235,62 +165,8 @@ public class DefaultProvider implements Provider { } } - @Override - public ApplicationExtensions extensionsFor(ApplicationContext context) { - - try { - - InputStream config = context.application().getResourceAsStream(extensions_file_path); - - if (config == null) { - - log.trace("{} uses default extensions as it does not include {}", context.name(), extensions_file_path); - - // it's in a library, using - config = getClass().getResourceAsStream(default_extensions_file_path); - - if (config == null) - throw new IllegalStateException( - "invalid distribution: cannot find " + default_extensions_file_path); - - } else - log.info("{} uses custom extensions @ {}", context.name(), extensions_file_path); - - ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - - return binder.bindExtensions(config); - - } catch (RuntimeException e) { - - throw new RuntimeException( - "cannot install extensions for application @ " + context.name() + " (see cause) ", e); - - } - } - - @Override - public SmartGearsConfiguration smartgearsConfiguration() { - - try { - - InputStream config = getClass().getResourceAsStream(library_configuration_file_path); - - if (config == null) - throw new IllegalStateException("invalid distribution: cannot find " + library_configuration_file_path); - - SmartGearsConfigurationBinder binder = new SmartGearsConfigurationBinder(); - - SmartGearsConfiguration configuration = binder.bind(config); - - configuration.validate(); - - return configuration; - } catch (RuntimeException e) { - - throw new RuntimeException("cannot read library configuration (see cause) ", e); - - } - + public List extensionsFor(ApplicationContext context){ + return List.of(new RemoteResource()); } // helpers @@ -305,7 +181,7 @@ public class DefaultProvider implements Provider { ApplicationConfigurationBinder binder = new ApplicationConfigurationBinder(); - return binder.bind(config); + return binder.load(config); } catch (RuntimeException e) { diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index fc80175..c0c61b6 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -4,11 +4,10 @@ import java.util.List; import javax.servlet.ServletContext; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.publishing.Publisher; @@ -25,8 +24,9 @@ public interface Provider { /** * Returns the runtime properties. * @return the properties. - */ + SmartGearsConfiguration smartgearsConfiguration(); + */ /** * Assembles and returns the context of the container. @@ -65,12 +65,7 @@ public interface Provider { */ ApplicationHandlers handlersFor(ApplicationContext application); - /** - * Returns the API extensions associated with a given application. - * @param application the context of the application - * @return the extensions - */ - ApplicationExtensions extensionsFor(ApplicationContext application); + List extensionsFor(ApplicationContext application); } diff --git a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java index 9c74a8e..7c432ff 100644 --- a/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java +++ b/src/main/java/org/gcube/smartgears/security/defaults/DefaultAuthorizationProvider.java @@ -12,8 +12,8 @@ import org.gcube.common.keycloak.model.AccessToken.Access; import org.gcube.common.keycloak.model.ModelUtils; import org.gcube.common.keycloak.model.TokenResponse; import org.gcube.common.security.ContextBean; -import org.gcube.common.security.secrets.AccessTokenSecret; import org.gcube.common.security.secrets.Secret; +import org.gcube.common.security.secrets.UmaTokenSecret; import org.gcube.smartgears.security.AuthorizationProvider; import org.gcube.smartgears.security.SimpleCredentials; import org.slf4j.Logger; @@ -61,7 +61,7 @@ public class DefaultAuthorizationProvider implements AuthorizationProvider { public Secret getSecretForContext(String context) { try { TokenResponse response = client.queryUMAToken(new URL(this.endpoint), credentials.getClientID(), credentials.getSecret(), context, null); - return new AccessTokenSecret(response.getAccessToken()); + return new UmaTokenSecret(response.getAccessToken()); } catch (Exception e) { LOG.error("error getting OIDToken from keycloak",e); diff --git a/src/main/resources/META-INF/default-extensions.xml b/src/main/resources/META-INF/default-extensions.xml deleted file mode 100644 index 26845b3..0000000 --- a/src/main/resources/META-INF/default-extensions.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - - diff --git a/src/main/resources/META-INF/profile.xml b/src/main/resources/META-INF/profile.xml deleted file mode 100644 index 3bc929b..0000000 --- a/src/main/resources/META-INF/profile.xml +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Service - - ${description} - ${serviceClass} - common-smartgears - 1.0.0 - - - ${description} - common-smartgears - 4.0.0-SNAPSHOT - - org.gcube.core - common-smartgears - 4.0.0-SNAPSHOT - - Library - - common-smartgears-4.0.0-SNAPSHOT.jar - - - - - - diff --git a/src/test/java/utils/ConfigurationTest.java b/src/test/java/utils/ConfigurationTest.java new file mode 100644 index 0000000..1765ab2 --- /dev/null +++ b/src/test/java/utils/ConfigurationTest.java @@ -0,0 +1,88 @@ +package utils; + +import java.io.InputStream; +import java.util.List; + +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.smartgears.configuration.PersistenceConfiguration; +import org.gcube.smartgears.configuration.application.ApplicationConfiguration; +import org.gcube.smartgears.configuration.application.GCubeExclude; +import org.gcube.smartgears.persistence.LocalWriter; +import org.gcube.smartgears.persistence.LocalWriterConfiguration; +import org.junit.Test; +import org.yaml.snakeyaml.Yaml; + +import junit.framework.Assert; + +public class ConfigurationTest { + + static final String yamlConf = "name: test\n" + + "group: group\n" + + "version: 1.0.0\n" + + "description: pippo\n" + + "proxable: true\n" + + "excludes:\n" + + "- path: /pippo/*\n" + + "- handlers: [H1, H2]\n" + + " path: /trip\n" + + "persistence:\n" + + " implementationClass: org.gcube.smartgears.persistence.LocalWriter\n" + + " writerConfiguration:\n" + + " className: org.gcube.smartgears.persistence.LocalWriterConfiguration\n" + + " location: /tmp"; + + static final String yamlConfBase = "name: test\n" + + "group: group\n" + + "version: 1.0.0\n" + + "description: pippo"; + + @Test + public void deserialize() { + Yaml yaml = new Yaml(); + InputStream inputStream = this.getClass() + .getClassLoader() + .getResourceAsStream("applicationTest.yaml"); + ApplicationConfiguration customer = yaml.load(inputStream); + + } + + @Test + public void serialize() throws Exception{ + ApplicationConfiguration configuration =new ApplicationConfiguration(); + configuration.name("test").serviceClass("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip")); + configuration.persistenceConfiguration(new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration("/tmp"))); + /* + ObjectMapper mapper = new ObjectMapper(); + String value = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(configuration); + System.out.println(value); + Map res = mapper.readValue(value, Map.class); + + + + Yaml yaml = new Yaml(); + String yamlValue = yaml.dump(res); + System.out.println(yamlValue); + */ + + Yaml yaml = new Yaml(); + ObjectMapper mapper = new ObjectMapper(); + String mapAsString = mapper.writeValueAsString(yaml.load(yamlConf)); + System.out.println(mapAsString); + + ApplicationConfiguration conf2 = mapper.readValue(mapAsString, ApplicationConfiguration.class); + Assert.assertTrue(configuration.equals(conf2)); + } + + @Test + public void serializeBase() throws Exception{ + ObjectMapper mapper = new ObjectMapper(); + Yaml yaml = new Yaml(); + + String mapAsString = mapper.writeValueAsString(yaml.load(yamlConfBase)); + System.out.println(mapAsString); + + ApplicationConfiguration conf2 = mapper.readValue(mapAsString, ApplicationConfiguration.class); + Assert.assertEquals("test", conf2.name()); + + } +} diff --git a/src/test/java/utils/PersistenceWriterTest.java b/src/test/java/utils/PersistenceWriterTest.java index a73e280..23abf16 100644 --- a/src/test/java/utils/PersistenceWriterTest.java +++ b/src/test/java/utils/PersistenceWriterTest.java @@ -4,6 +4,7 @@ import java.io.File; import org.gcube.common.validator.annotations.IsValid; import org.gcube.common.validator.annotations.NotNull; +import org.gcube.smartgears.configuration.ComponentConfiguration; import org.gcube.smartgears.persistence.PersistenceWriter; public class PersistenceWriterTest implements PersistenceWriter{ @@ -33,5 +34,10 @@ public class PersistenceWriterTest implements PersistenceWriter{ public long getFreeSpace() { return 0; } + + @Override + public void configure(ComponentConfiguration configuration) { + + } } diff --git a/src/test/java/utils/TestProvider.java b/src/test/java/utils/TestProvider.java index 7dd0014..6d27894 100644 --- a/src/test/java/utils/TestProvider.java +++ b/src/test/java/utils/TestProvider.java @@ -1,15 +1,15 @@ package utils; import java.io.File; +import java.util.List; import javax.servlet.ServletContext; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.extensions.ApplicationExtension; import org.gcube.smartgears.provider.DefaultProvider; public class TestProvider extends DefaultProvider { @@ -21,7 +21,7 @@ public class TestProvider extends DefaultProvider { public ApplicationContext context; public ApplicationConfiguration configuration; public ApplicationHandlers handlers; - public ApplicationExtensions extensions; + public List extensions; public void use(ApplicationConfiguration configuration) { @@ -32,18 +32,18 @@ public class TestProvider extends DefaultProvider { this.handlers=handlers; } - public void use(ApplicationExtensions extensions) { + public void use(List extensions) { this.extensions=extensions; } - + /* @Override public SmartGearsConfiguration smartgearsConfiguration() { SmartGearsConfiguration conf = new SmartGearsConfiguration(); conf.version("0.0.1-TEST"); return conf ; - } + }*/ @Override @@ -57,7 +57,7 @@ public class TestProvider extends DefaultProvider { } @Override - public ApplicationExtensions extensionsFor(ApplicationContext context) { + public List extensionsFor(ApplicationContext context) { return extensions==null?super.extensionsFor(context):extensions; } } diff --git a/src/test/java/utils/TestUtils.java b/src/test/java/utils/TestUtils.java deleted file mode 100644 index a043481..0000000 --- a/src/test/java/utils/TestUtils.java +++ /dev/null @@ -1,155 +0,0 @@ -package utils; - -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.List; - -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBException; - -import org.gcube.smartgears.configuration.application.ApplicationConfiguration; -import org.gcube.smartgears.configuration.application.ApplicationExtensions; -import org.gcube.smartgears.configuration.application.ApplicationHandlers; -import org.gcube.smartgears.configuration.application.DefaultApplicationConfiguration; -import org.gcube.smartgears.extensions.ApplicationExtension; -import org.gcube.smartgears.handlers.application.ApplicationHandler; - - -public class TestUtils { - - - public static String location = "/tmp/ghn-home"; - public static String context_root = "test-app"; - public static String context_root_path = "/" + context_root; - public static String servlet_name = "test"; - public static String scope = "/gcube/devsec"; - - public static class Box { - - T t; - - public void put(T t) { - this.t=t; - } - - public T get() { - return t; - } - - } - - - /** - * Serialises a {@link ApplicationConfiguration} to XML. - * - * @param config the configuration - * @return the serialisation - * @throws RuntimeException if the configuration cannot be serialised - */ - public static String bind(ApplicationConfiguration config) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(DefaultApplicationConfiguration.class); - if (config.persistence()!=null) - classes.add(config.persistence().getClass()); - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(config, writer); - - return writer.toString(); - - - } catch (JAXBException e) { - - throw new RuntimeException("invalid application configuration", e); - - } - } - - /** - * Serialises application handlers. - * - * @param handlers the handlers - * @return the serialisation - * @throws RuntimeException if the handlers cannot be serialised - */ - public static String bind(ApplicationHandlers handlers) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(ApplicationHandlers.class); - - for (ApplicationHandler h : handlers.lifecycleHandlers()) - classes.add(h.getClass()); - - for (ApplicationHandler h : handlers.requestHandlers()) - classes.add(h.getClass()); - - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(handlers, writer); - - return writer.toString(); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid handler configuration", e); - - } - } - - /** - * Serialises application extensions. - * - * @param extensions the extensions - * @return the serialisation - * @throws RuntimeException if the extensions cannot be serialised - */ - public static String bind(ApplicationExtensions extensions) { - - try { - - //collect handler classes - List> classes = new ArrayList>(); - - classes.add(ApplicationExtensions.class); - - for (ApplicationExtension h : extensions.extensions()) - classes.add(h.getClass()); - - - //serialises configuration - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - StringWriter writer = new StringWriter(); - - ctx.createMarshaller().marshal(extensions, writer); - - return writer.toString(); - - } catch (JAXBException e) { - - throw new RuntimeException("invalid handler configuration", e); - - } - } - -} diff --git a/src/test/resources/application.yaml b/src/test/resources/application.yaml new file mode 100644 index 0000000..c684c27 --- /dev/null +++ b/src/test/resources/application.yaml @@ -0,0 +1,18 @@ +name: test +group: group +version: 1.0.0 +#not mandatory +description: pippo +#not mandatory +proxable: true +#not mandatory +excludes: + - path: /pippo/* + - handlers: [H1, H2] + path: /trip +#not mandatory +persistence: + implementationClass: org.gcube.smartgears.persistence.LocalWriter + writerConfiguration: + className: org.gcube.smartgears.persistence.LocalWriterConfiguration + location: /tmp \ No newline at end of file From be3d37d6c31dc5772dd64d0faa110c54413fa3d6 Mon Sep 17 00:00:00 2001 From: lucio Date: Fri, 31 Mar 2023 14:16:23 +0200 Subject: [PATCH 49/49] updated --- .../META-INF/smartgears-config.ini | 2 + .../META-INF/smartgears-config.xml | 2 - pom.xml | 15 +- .../SmartgearsConfiguration.java | 15 ++ .../application/ApplicationConfiguration.java | 8 +- .../ApplicationConfigurationBinder.java | 141 ++++++++++-------- .../ContainerConfigurationBinder.java | 11 ++ .../library/SmartGearsConfiguration.java | 75 ---------- .../smartgears/extensions/HttpController.java | 1 - .../smartgears/extensions/HttpExtension.java | 13 +- .../resource/ConfigurationResource.java | 8 +- .../resource/FrontPageResource.java | 3 +- .../extensions/resource/HealthResource.java | 19 +-- .../request/RequestAccounting.java | 6 +- .../application/request/RequestMetrics.java | 1 - .../smartgears/health/HealthManager.java | 3 +- .../gcube/smartgears/health/HealthTask.java | 8 +- .../smartgears/provider/DefaultProvider.java | 9 ++ .../gcube/smartgears/provider/Provider.java | 2 + .../org/gcube/smartgears/utils/Utils.java | 2 +- ...smartgears.extensions.ApplicationExtension | 1 - src/test/java/utils/ConfigurationTest.java | 4 +- 22 files changed, 157 insertions(+), 192 deletions(-) create mode 100644 gcube/extra-resources/META-INF/smartgears-config.ini delete mode 100644 gcube/extra-resources/META-INF/smartgears-config.xml create mode 100644 src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java delete mode 100644 src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java delete mode 100644 src/main/resources/META-INF/services/org.gcube.smartgears.extensions.ApplicationExtension diff --git a/gcube/extra-resources/META-INF/smartgears-config.ini b/gcube/extra-resources/META-INF/smartgears-config.ini new file mode 100644 index 0000000..62fedff --- /dev/null +++ b/gcube/extra-resources/META-INF/smartgears-config.ini @@ -0,0 +1,2 @@ +[smartgears] +version = ${version} \ No newline at end of file diff --git a/gcube/extra-resources/META-INF/smartgears-config.xml b/gcube/extra-resources/META-INF/smartgears-config.xml deleted file mode 100644 index 5b56d71..0000000 --- a/gcube/extra-resources/META-INF/smartgears-config.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/pom.xml b/pom.xml index a0bc221..5d2e02e 100644 --- a/pom.xml +++ b/pom.xml @@ -28,8 +28,8 @@ 8.0.42 2.25.1 UTF-8 - 1.8 - 1.8 + 11 + 11 scm:git:https://code-repo.d4science.org/gCubeSystem/common-smartgears.git @@ -106,10 +106,6 @@ org.gcube.common.security gcube-secrets - - javax.ws.rs - javax.ws.rs-api - javax.servlet javax.servlet-api @@ -151,12 +147,7 @@ org.glassfish.jersey.core jersey-client - test - - - org.apache.tomcat.embed - tomcat-embed-core - ${tomcat.version} + 2.25.1 test diff --git a/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java new file mode 100644 index 0000000..43d6311 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/configuration/SmartgearsConfiguration.java @@ -0,0 +1,15 @@ +package org.gcube.smartgears.configuration; + +public class SmartgearsConfiguration { + + private String version; + + public SmartgearsConfiguration(String version) { + super(); + this.version = version; + } + + public String getVersion() { + return version; + } +} diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java index c8624da..8f46c9d 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfiguration.java @@ -48,9 +48,9 @@ public class ApplicationConfiguration { private boolean proxable = true; - Set excludes= null; + Set excludes= new HashSet<>(); - Set includes= null; + Set includes= new HashSet<>(); @NotEmpty @JsonProperty("persistence") PersistenceConfiguration persistenceConfiguration; @@ -103,12 +103,12 @@ public class ApplicationConfiguration { return this; } - public String serviceClass() { + public String group() { return group; } - public ApplicationConfiguration serviceClass(String group) { + public ApplicationConfiguration group(String group) { this.group=group; return this; } diff --git a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java index 144d57a..f7699a1 100644 --- a/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/application/ApplicationConfigurationBinder.java @@ -1,16 +1,21 @@ package org.gcube.smartgears.configuration.application; +import java.io.File; import java.io.InputStream; import java.util.LinkedList; import java.util.List; import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; +import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; import org.gcube.smartgears.handlers.application.RequestHandler; import org.gcube.smartgears.handlers.application.lifecycle.ApplicationProfileManager; import org.gcube.smartgears.handlers.application.request.RequestAccounting; import org.gcube.smartgears.handlers.application.request.RequestMetrics; import org.gcube.smartgears.handlers.application.request.RequestValidator; +import org.gcube.smartgears.persistence.LocalWriter; +import org.gcube.smartgears.persistence.LocalWriterConfiguration; +import org.gcube.smartgears.utils.Utils; import org.yaml.snakeyaml.Yaml; /** @@ -33,9 +38,22 @@ public class ApplicationConfigurationBinder { Yaml yaml = new Yaml(); ObjectMapper mapper = new ObjectMapper(); String mapAsString = mapper.writeValueAsString(yaml.load(stream)); - - return mapper.readValue(mapAsString, ApplicationConfiguration.class); - }catch (Exception e) { + + ApplicationConfiguration conf = mapper.readValue(mapAsString, ApplicationConfiguration.class); + + if (conf.persistenceConfiguration() == null) { + String location = String.format("%s/state/%s_%s", Utils.home(), conf.group(), conf.name()); + File dir = new File(location); + if (!dir.exists()) + dir.mkdirs(); + + conf.persistenceConfiguration( + new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration(location))); + + } + + return conf; + } catch (Exception e) { throw new RuntimeException(e); } } @@ -50,80 +68,79 @@ public class ApplicationConfigurationBinder { public ApplicationHandlers bindHandlers(ClassLoader classLoader) { List requestHandlers = new LinkedList(); - - //ADDING BASE Handler (order is important) + + // ADDING BASE Handler (order is important) requestHandlers.add(new RequestMetrics()); requestHandlers.add(new RequestValidator()); requestHandlers.add(new RequestAccounting()); - - //TODO scan RequestHAndler form classloader - - + + // TODO scan RequestHAndler form classloader + List lifecycleHandlers = new LinkedList(); - - //ADDING BASE Handler (order is important) + + // ADDING BASE Handler (order is important) lifecycleHandlers.add(new ApplicationProfileManager()); - - - //TODO scan ApplicationLifecycleHandler form classloader - + + // TODO scan ApplicationLifecycleHandler form classloader + return new ApplicationHandlers(lifecycleHandlers, requestHandlers); - + } - + /** * Returns the extensions of the application from their XML serialisation. * * @param stream the serialisation * @return the extensions * @throws RuntimeException if the serialisation is invalid - - public ApplicationExtensions bindExtensions(InputStream stream) { + * + * public ApplicationExtensions + * bindExtensions(InputStream stream) { + * + * //collects handler classes Set> classes = + * scanForExtensions(); + * + * try { + * + * JAXBContext ctx = + * JAXBContext.newInstance(classes.toArray(new + * Class[0])); + * + * return (ApplicationExtensions) + * ctx.createUnmarshaller().unmarshal(stream); + * + * } catch (JAXBException e) { + * + * throw unchecked(e); + * + * } finally { closeSafely(stream); } } + * + * + * + * private Set> scanForExtensions() throws + * RuntimeException { + * + * @SuppressWarnings("all") + * ServiceLoader handlerLoader = + * (ServiceLoader) + * ServiceLoader.load(ApplicationExtension.class); + * + * Set> scanned = new HashSet>(); + * + * for (ApplicationExtension handler : handlerLoader) { + * Class handlerClass = handler.getClass(); if + * (handlerClass.isInterface() || + * handlerClass.getModifiers() == Modifier.ABSTRACT) + * continue; else scanned.add(handlerClass); } + * + * //add top-level configuration + * scanned.add(ApplicationExtensions.class); + * + * return scanned; } + */ - //collects handler classes - Set> classes = scanForExtensions(); - - try { - - JAXBContext ctx = JAXBContext.newInstance(classes.toArray(new Class[0])); - - return (ApplicationExtensions) ctx.createUnmarshaller().unmarshal(stream); - - } catch (JAXBException e) { - - throw unchecked(e); - - } - finally { - closeSafely(stream); - } - } - - - - private Set> scanForExtensions() throws RuntimeException { - - @SuppressWarnings("all") - ServiceLoader handlerLoader = (ServiceLoader) ServiceLoader.load(ApplicationExtension.class); - - Set> scanned = new HashSet>(); - - for (ApplicationExtension handler : handlerLoader) { - Class handlerClass = handler.getClass(); - if (handlerClass.isInterface() || handlerClass.getModifiers() == Modifier.ABSTRACT) - continue; - else - scanned.add(handlerClass); - } - - //add top-level configuration - scanned.add(ApplicationExtensions.class); - - return scanned; - } - */ - public void scanForApplicationHandlers(ClassLoader currentClassLoader) { // TODO Auto-generated method stub } + } diff --git a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java index 686aba5..382a803 100644 --- a/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java +++ b/src/main/java/org/gcube/smartgears/configuration/container/ContainerConfigurationBinder.java @@ -14,6 +14,7 @@ import org.gcube.smartgears.configuration.ComponentConfiguration; import org.gcube.smartgears.configuration.ConfiguredWith; import org.gcube.smartgears.configuration.PersistenceConfiguration; import org.gcube.smartgears.configuration.ProxyAddress; +import org.gcube.smartgears.configuration.SmartgearsConfiguration; import org.gcube.smartgears.handlers.container.ContainerHandler; import org.gcube.smartgears.handlers.container.lifecycle.AccountingManager; import org.gcube.smartgears.handlers.container.lifecycle.ContainerProfileManager; @@ -194,4 +195,14 @@ public class ContainerConfigurationBinder { return Collections.emptyList(); } + public SmartgearsConfiguration loadSmartgearsProperty() { + try { + Ini configurator = new Ini(this.getClass().getResourceAsStream("smartgears-config.ini")); + String version = configurator.get("smartgears").get("version"); + return new SmartgearsConfiguration(version); + }catch (Exception e) { + throw new RuntimeException(e); + } + } + } diff --git a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java b/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java deleted file mode 100644 index f628c6a..0000000 --- a/src/main/java/org/gcube/smartgears/configuration/library/SmartGearsConfiguration.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.gcube.smartgears.configuration.library; - -import java.util.ArrayList; -import java.util.List; - -import org.gcube.common.validator.ValidationError; -import org.gcube.common.validator.Validator; -import org.gcube.common.validator.ValidatorFactory; -import org.gcube.common.validator.annotations.NotEmpty; - -public class SmartGearsConfiguration { - - @NotEmpty - private String version; - - public SmartGearsConfiguration(){ - } - - public String version() { - return version; - } - - public SmartGearsConfiguration version(String version) { - this.version=version; - return this; - } - - - /** - * Validates this configuration - * - * @throws IllegalStateException if the configuration is invalid - */ - public void validate() { - - List msgs = new ArrayList(); - - Validator validator = ValidatorFactory.validator(); - - for (ValidationError error : validator.validate(this)) - msgs.add(error.toString()); - - if (!msgs.isEmpty()) - throw new IllegalStateException("invalid configuration: "+msgs); - - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + ((version == null) ? 0 : version.hashCode()); - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) - return true; - if (obj == null) - return false; - if (getClass() != obj.getClass()) - return false; - SmartGearsConfiguration other = (SmartGearsConfiguration) obj; - if (version == null) { - if (other.version != null) - return false; - } else if (!version.equals(other.version)) - return false; - return true; - } - - - -} diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpController.java b/src/main/java/org/gcube/smartgears/extensions/HttpController.java index c9f6437..cab2e79 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpController.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpController.java @@ -75,7 +75,6 @@ public class HttpController extends HttpExtension { @Override public void stop(){ - super.stop(); for (ApiResource resource : resources.values()) resource.stop(); diff --git a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java index 0b76baf..ef0e3e8 100644 --- a/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java +++ b/src/main/java/org/gcube/smartgears/extensions/HttpExtension.java @@ -6,7 +6,6 @@ import java.util.HashSet; import java.util.Set; import javax.servlet.http.HttpServlet; -import javax.ws.rs.HttpMethod; import org.gcube.common.validator.annotations.NotEmpty; import org.gcube.smartgears.configuration.application.GCubeExclude; @@ -26,12 +25,12 @@ public abstract class HttpExtension extends HttpServlet implements ApplicationEx * */ public static enum Method { - GET(HttpMethod.GET), - PUT(HttpMethod.PUT), - POST(HttpMethod.POST), - HEAD(HttpMethod.HEAD), - DELETE(HttpMethod.DELETE), - OPTIONS(HttpMethod.OPTIONS); + GET("GET"), + PUT("PUT"), + POST("POST"), + HEAD("HEAD"), + DELETE("DELETE"), + OPTIONS("OPTIONS"); private String value; diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java index 534b46a..ded8c0d 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/ConfigurationResource.java @@ -1,6 +1,6 @@ package org.gcube.smartgears.extensions.resource; -import static org.gcube.smartgears.Constants.application_xml; +import static org.gcube.smartgears.Constants.application_json; import static org.gcube.smartgears.extensions.HttpExtension.Method.GET; import java.io.IOException; @@ -9,7 +9,7 @@ import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import org.gcube.common.resources.gcore.Resources; +import org.gcube.com.fasterxml.jackson.databind.ObjectMapper; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; @@ -26,7 +26,7 @@ public class ConfigurationResource extends ApiResource { public static final String mapping = "/configuration"; - private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_xml)); + private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json)); ConfigurationResource() { super(signature); @@ -37,7 +37,7 @@ public class ConfigurationResource extends ApiResource { public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { ApplicationConfiguration config = context().configuration(); - Resources.marshal(config,resp.getWriter()); + new ObjectMapper().writeValue(resp.getWriter(), config); } } diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java index e038b33..c008853 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/FrontPageResource.java @@ -21,6 +21,7 @@ import javax.servlet.http.HttpServletResponse; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; +import org.gcube.smartgears.provider.ProviderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,7 +93,7 @@ public class FrontPageResource extends ApiResource { values.put("status", context().lifecycle().state().toString()); - //values.put("smartgears-version", provider().smartgearsConfiguration().version()); + values.put("smartgears-version", ProviderFactory.provider().smartgearsConfiguration().getVersion()); return values; } diff --git a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java index 54e774b..a084d12 100644 --- a/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java +++ b/src/main/java/org/gcube/smartgears/extensions/resource/HealthResource.java @@ -19,7 +19,6 @@ import org.gcube.common.health.api.ReadinessChecker; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.extensions.ApiResource; import org.gcube.smartgears.extensions.ApiSignature; -import org.gcube.smartgears.handlers.application.request.RequestError; import org.gcube.smartgears.health.HealthManager; import org.gcube.smartgears.health.HealthResponse; import org.gcube.smartgears.health.HealthTask; @@ -39,8 +38,6 @@ public class HealthResource extends ApiResource { public static final String mapping = "/health"; - public static final String readiness_mapping = "/readiness"; - private static final ApiSignature signature = handles(mapping).with(method(GET).produces(application_json)); private HealthManager manager; @@ -71,14 +68,14 @@ public class HealthResource extends ApiResource { manager.register((HealthCheck) readnessClass.getDeclaredConstructor().newInstance()); log.info("added class {} to health manager", readnessClass.getCanonicalName()); } catch (Throwable e) { - log.error("healthChecher class {} cannot be instantiated", readnessClass.getCanonicalName(), e); + log.error("healthChecker class {} cannot be instantiated", readnessClass.getCanonicalName(), e); } task = new HealthTask(manager); timer = new Timer(true); - timer.scheduleAtFixedRate(task, 0, 10000); + timer.scheduleAtFixedRate(task, 10000, 60000); super.init(context); } @@ -93,14 +90,7 @@ public class HealthResource extends ApiResource { PrintWriter out = resp.getWriter(); resp.setContentType("application/json"); resp.setCharacterEncoding("UTF-8"); - Object response = null; - - String contextpath = req.getContextPath(); - log.info("context path is {}", req.getContextPath()); - if (contextpath.endsWith(readiness_mapping)) - response = readiness(); - else - RequestError.resource_notfound_error.fire(); + HealthResponse response = readiness(); new ObjectMapper().writeValue(out, response); @@ -110,5 +100,6 @@ public class HealthResource extends ApiResource { public HealthResponse readiness() { return task.getResponse(); } - + + } \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java index c51990e..db65ce8 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestAccounting.java @@ -48,7 +48,7 @@ public class RequestAccounting extends RequestHandler { startCallThreadLocal.set(System.currentTimeMillis()); log.info("REQUEST START ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} ", appContext.configuration().name(), - appContext.configuration().serviceClass(), InnerMethodName.instance.get(), caller, + appContext.configuration().group(), InnerMethodName.instance.get(), caller, e.request().getRemoteHost(), context); } @@ -90,7 +90,7 @@ public class RequestAccounting extends RequestHandler { */ log.info("REQUEST SERVED ON {}:{}({}) CALLED FROM {}@{} IN SCOPE {} {}(CODE {}) IN {} millis", - appContext.configuration().name(), appContext.configuration().serviceClass(), + appContext.configuration().name(), appContext.configuration().group(), InnerMethodName.instance.get(), caller, callerIp, context, success ? "SUCCEDED" : "FAILED", e.response().getStatus(), durationInMillis); @@ -115,7 +115,7 @@ public class RequestAccounting extends RequestHandler { serviceUsageRecord.setConsumerId(caller); serviceUsageRecord.setCallerQualifier(callerQualifier); serviceUsageRecord.setScope(gcubeContext); - serviceUsageRecord.setServiceClass(appContext.configuration().serviceClass()); + serviceUsageRecord.setServiceClass(appContext.configuration().group()); serviceUsageRecord.setServiceName(appContext.configuration().name()); serviceUsageRecord.setHost(appContext.container().configuration().hostname() + ":" diff --git a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java index 719a173..30793be 100644 --- a/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java +++ b/src/main/java/org/gcube/smartgears/handlers/application/request/RequestMetrics.java @@ -38,7 +38,6 @@ public class RequestMetrics extends RequestHandler { public void handleResponse(ResponseEvent e) { String statusCode = Integer.toString(e.response().getStatus()); Metrics.globalRegistry.timer(HTTP_REQUEST_METRICS_NAME, "status", statusCode).record(Duration.ofMillis(System.currentTimeMillis() - startCallThreadLocal.get())); - Metrics.globalRegistry.counter(HTTP_REQUEST_METRICS_NAME, "status", statusCode); startCallThreadLocal.remove(); log.debug("metrics for current call saved"); } diff --git a/src/main/java/org/gcube/smartgears/health/HealthManager.java b/src/main/java/org/gcube/smartgears/health/HealthManager.java index 64dcab0..2fe5e40 100644 --- a/src/main/java/org/gcube/smartgears/health/HealthManager.java +++ b/src/main/java/org/gcube/smartgears/health/HealthManager.java @@ -1,12 +1,13 @@ package org.gcube.smartgears.health; +import java.util.LinkedList; import java.util.List; import org.gcube.common.health.api.HealthCheck; public class HealthManager { - private List checks; + private List checks = new LinkedList<>(); public void register(HealthCheck check){ checks.add(check); diff --git a/src/main/java/org/gcube/smartgears/health/HealthTask.java b/src/main/java/org/gcube/smartgears/health/HealthTask.java index 61aa28b..ef755d6 100644 --- a/src/main/java/org/gcube/smartgears/health/HealthTask.java +++ b/src/main/java/org/gcube/smartgears/health/HealthTask.java @@ -7,9 +7,13 @@ import java.util.stream.Collectors; import org.gcube.common.health.api.HealthCheck; import org.gcube.common.health.api.Status; import org.gcube.common.health.api.response.HealthCheckResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class HealthTask extends TimerTask{ + private static final Logger log = LoggerFactory.getLogger(HealthTask.class); + private HealthResponse response; private HealthManager healthManager; @@ -20,12 +24,14 @@ public class HealthTask extends TimerTask{ @Override public void run() { + List checks = healthManager.getChecks(); List responses = checks.stream().map(c -> this.wrap(c)).collect(Collectors.toList()); Status totalStatus = responses.stream().anyMatch(r -> r.getStatus().equals(Status.DOWN)) ? Status.DOWN : Status.UP; this.response = new HealthResponse(totalStatus, responses); + log.debug("health task executed with total status {}",totalStatus); } public HealthResponse getResponse() { @@ -36,7 +42,7 @@ public class HealthTask extends TimerTask{ try { return check.check(); }catch (Throwable t) { - return HealthCheckResponse.builder(check.getName()).down().withMessage("unexpected error executing check").build(); + return HealthCheckResponse.builder(check.getName()).down().withMessage(t.getMessage()).build(); } } diff --git a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java index 8b72b56..1308cc8 100644 --- a/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java +++ b/src/main/java/org/gcube/smartgears/provider/DefaultProvider.java @@ -18,6 +18,7 @@ import javax.servlet.ServletContext; import org.gcube.common.events.Hub; import org.gcube.common.events.impl.DefaultHub; import org.gcube.common.security.credentials.Credentials; +import org.gcube.smartgears.configuration.SmartgearsConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfiguration; import org.gcube.smartgears.configuration.application.ApplicationConfigurationBinder; import org.gcube.smartgears.configuration.application.ApplicationHandlers; @@ -276,9 +277,17 @@ public class DefaultProvider implements Provider { return this.publishers; } + @Override + public SmartgearsConfiguration smartgearsConfiguration() { + ContainerConfigurationBinder binder = new ContainerConfigurationBinder(); + return binder.loadSmartgearsProperty(); + } + /* * @Override public AuthorizationProvider authorizationProvider() { return * containerContext.authorizationProvider(); } */ + + } diff --git a/src/main/java/org/gcube/smartgears/provider/Provider.java b/src/main/java/org/gcube/smartgears/provider/Provider.java index c0c61b6..80ae602 100644 --- a/src/main/java/org/gcube/smartgears/provider/Provider.java +++ b/src/main/java/org/gcube/smartgears/provider/Provider.java @@ -4,6 +4,7 @@ import java.util.List; import javax.servlet.ServletContext; +import org.gcube.smartgears.configuration.SmartgearsConfiguration; import org.gcube.smartgears.configuration.application.ApplicationHandlers; import org.gcube.smartgears.context.application.ApplicationContext; import org.gcube.smartgears.context.container.ContainerContext; @@ -67,5 +68,6 @@ public interface Provider { List extensionsFor(ApplicationContext application); + SmartgearsConfiguration smartgearsConfiguration(); } diff --git a/src/main/java/org/gcube/smartgears/utils/Utils.java b/src/main/java/org/gcube/smartgears/utils/Utils.java index 43caaa2..42c1a4a 100644 --- a/src/main/java/org/gcube/smartgears/utils/Utils.java +++ b/src/main/java/org/gcube/smartgears/utils/Utils.java @@ -214,7 +214,7 @@ public class Utils { public static ServiceInfo getServiceInfo(ApplicationContext application){ String hostedin = String.format("%s_%d", application.container().configuration().hostname(), application.container().configuration().port()); return - new ServiceInfo(new ServiceIdentifier(application.configuration().serviceClass(), application.configuration().name(), hostedin)); + new ServiceInfo(new ServiceIdentifier(application.configuration().group(), application.configuration().name(), hostedin)); } public static Throwable getCause(Throwable e) { diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.extensions.ApplicationExtension b/src/main/resources/META-INF/services/org.gcube.smartgears.extensions.ApplicationExtension deleted file mode 100644 index 3a14165..0000000 --- a/src/main/resources/META-INF/services/org.gcube.smartgears.extensions.ApplicationExtension +++ /dev/null @@ -1 +0,0 @@ -org.gcube.smartgears.extensions.resource.RemoteResource \ No newline at end of file diff --git a/src/test/java/utils/ConfigurationTest.java b/src/test/java/utils/ConfigurationTest.java index 1765ab2..9948a84 100644 --- a/src/test/java/utils/ConfigurationTest.java +++ b/src/test/java/utils/ConfigurationTest.java @@ -42,14 +42,14 @@ public class ConfigurationTest { InputStream inputStream = this.getClass() .getClassLoader() .getResourceAsStream("applicationTest.yaml"); - ApplicationConfiguration customer = yaml.load(inputStream); + yaml.load(inputStream); } @Test public void serialize() throws Exception{ ApplicationConfiguration configuration =new ApplicationConfiguration(); - configuration.name("test").serviceClass("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip")); + configuration.name("test").group("group").description("pippo").version("1.0.0").excludes(new GCubeExclude("/pippo/*"), new GCubeExclude(List.of("H1","H2"), "/trip")); configuration.persistenceConfiguration(new PersistenceConfiguration(LocalWriter.class, new LocalWriterConfiguration("/tmp"))); /* ObjectMapper mapper = new ObjectMapper();