From b464f8b477dbb3714f3f3e00f0584e4ac96ca10d Mon Sep 17 00:00:00 2001 From: "michael.breu" <michael.breu@uibk.ac.at> Date: Tue, 2 Mar 2021 10:24:20 +0100 Subject: [PATCH] Intermediate commit --- .../service/PluginManagementService.java | 45 ++++- .../uibk/gitsearch/service/SearchService.java | 17 ++ .../service/ShoppingBasketService.java | 177 ++++++++++++++++++ .../service/dto/SearchResultsDTO.java | 71 +++++++ .../web/rest/PluginInterfaceResource.java | 18 +- 5 files changed, 322 insertions(+), 6 deletions(-) diff --git a/src/main/java/at/ac/uibk/gitsearch/service/PluginManagementService.java b/src/main/java/at/ac/uibk/gitsearch/service/PluginManagementService.java index 3f1e6eb82..0fe4fca3e 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/PluginManagementService.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/PluginManagementService.java @@ -1,7 +1,13 @@ package at.ac.uibk.gitsearch.service; +import java.net.URI; +import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.ws.rs.client.Client; @@ -10,10 +16,13 @@ import javax.ws.rs.client.WebTarget; import javax.ws.rs.core.MediaType; import org.codeability.sharing.plugins.api.SharingPluginConfig; +import org.codeability.sharing.plugins.api.SharingPluginConfig.Action; import org.glassfish.jersey.client.ClientConfig; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Service; + +import com.fasterxml.jackson.jaxrs.json.JacksonJsonProvider; /** * management services for plugins. * @author Michael Breu @@ -26,7 +35,7 @@ public class PluginManagementService { "http://localhost:8081/api/sharing/config" }; - private static SharingPluginConfig[] registeredPluginConfigs; + private static Map<String, SharingPluginConfig> registeredPluginConfigs = new HashMap<>(); private final Logger log = LoggerFactory.getLogger(PluginManagementService.class); @@ -37,7 +46,7 @@ public class PluginManagementService { for(String registeredPlugin: registeredPlugins) { ClientConfig restClientConfig = new ClientConfig(); - + restClientConfig.register(JacksonJsonProvider.class); Client client = ClientBuilder.newClient(restClientConfig); WebTarget target = client.target(registeredPlugin); @@ -47,13 +56,43 @@ public class PluginManagementService { request(). accept(MediaType.APPLICATION_JSON). get(SharingPluginConfig.class); + absolutizeURLs(registeredPlugin, config); results.add(config); } catch (Exception e) { log.error("Cannot load plugin at {}", registeredPlugin, e); } - registeredPluginConfigs = (SharingPluginConfig[]) results.toArray(); + registeredPluginConfigs = results.stream().collect(Collectors.toMap(c -> c.getPluginName(), c -> c)); + } + } + + public void absolutizeURLs(String baseURL, SharingPluginConfig config) throws URISyntaxException { + for(Action action: config.getActions()) { + try { + URI actionURI = new URI(action.getImportServiceURL()); + if(!actionURI.isAbsolute()) { + action.setImportServiceURL(actionURI.resolve(baseURL).toASCIIString()); + } + } catch (URISyntaxException e) { + log.error("Cannot handle url {} in config {} from {}", action.getImportServiceURL(), config.getPluginName(), baseURL); + throw e; + } + + } + } + + public String getRedirectURL(String pluginName, String actionName) { + final SharingPluginConfig sharingPluginConfig = registeredPluginConfigs.get(pluginName); + if(sharingPluginConfig==null) return null; + for(Action action: sharingPluginConfig.getActions()) { + if(action.getActionName().equals(actionName)) { + return action.getImportServiceURL(); + } } + return null; } + public Collection<SharingPluginConfig> getRegisteredPluginConfigs() { + return registeredPluginConfigs.values(); + } } diff --git a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java index 2e1bb5a94..484d0606a 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/SearchService.java @@ -11,6 +11,7 @@ import java.util.Map.Entry; import java.util.Optional; import java.util.stream.Collectors; +import org.codeability.sharing.plugins.api.SharingPluginConfig.Action; import org.gitlab4j.api.Constants.TokenType; import org.gitlab4j.api.GitLabApi; import org.gitlab4j.api.GitLabApiException; @@ -32,6 +33,7 @@ import at.ac.uibk.gitsearch.security.jwt.TokenProvider; import at.ac.uibk.gitsearch.service.dto.AutoCompleteEntry; import at.ac.uibk.gitsearch.service.dto.SearchInputDTO; import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO; +import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO.PluginActionInfo; import at.ac.uibk.gitsearch.service.dto.SearchResultsDTO.SearchResultDTO; /** @@ -47,6 +49,8 @@ public class SearchService { protected MetaDataRepository metaDataRepository; @Autowired protected TokenProvider tokenProvider; + @Autowired + protected PluginManagementService pluginManagementService; /** just for test implementation **/ public static int NUM_TESTRESULTS = 23; @@ -124,7 +128,20 @@ public class SearchService { } } + + + final PluginActionInfo[] allPluginActions = (PluginActionInfo[]) pluginManagementService.getRegisteredPluginConfigs().stream().map( + config -> { + List<PluginActionInfo> result = new ArrayList<>(); + for(Action action: config.getActions()) { + result.add(new PluginActionInfo(config.getPluginName(), action.getActionName(), "Export to " + action.getActionName())); + } + return result; + } + ).flatMap(List<PluginActionInfo>::stream).collect(Collectors.toList()).toArray(); + pageDetails.getSearchResult().stream().forEach( + r -> r.setSupportedActions(allPluginActions)); final GitLabApi gitLabApif = gitLabApi; pageDetails.setSearchResult(pageDetails.getSearchResult().stream().filter(p->testAccess(p, gitLabApif)).collect(Collectors.toList())); pageDetails.getSearchResult().stream().forEach(md -> fixImageURL(md, gitLabApif)); diff --git a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java index dcd2266dc..62260f394 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/ShoppingBasketService.java @@ -1,12 +1,20 @@ package at.ac.uibk.gitsearch.service; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + import org.codeability.sharing.plugins.api.ShoppingBasket; import org.codeability.sharing.plugins.api.ShoppingBasket.ExerciseInfo; import org.codeability.sharing.plugins.api.ShoppingBasket.UserInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + /** * Service for exercise/course search results * <p> @@ -14,6 +22,153 @@ import org.springframework.stereotype.Service; @Service public class ShoppingBasketService { + @Autowired + private PluginManagementService pluginManagementService; + + public static class ShoppingBasketRedirectInfoDTO { + private String redirectURL; + private String shoppingBasketToken; + private String callBackURL; + /** + * @return the redirectURL + */ + public String getRedirectURL() { + return redirectURL; + } + /** + * @param redirectURL the redirectURL to set + */ + public void setRedirectURL(String redirectURL) { + this.redirectURL = redirectURL; + } + /** + * @return the shoppingBasketToken + */ + public String getShoppingBasketToken() { + return shoppingBasketToken; + } + /** + * @param shoppingBasketToken the shoppingBasketToken to set + */ + public void setShoppingBasketToken(String shoppingBasketToken) { + this.shoppingBasketToken = shoppingBasketToken; + } + /** + * @return the callBackURL + */ + public String getCallBackURL() { + return callBackURL; + } + /** + * @param callBackURL the callBackURL to set + */ + public void setCallBackURL(String callBackURL) { + this.callBackURL = callBackURL; + } + } + + public static class ShoppingBasketInfoDTO { + private ItemInfoDTO[] itemInfos; + private String plugin; + private String action; + + public ShoppingBasketInfoDTO(ItemInfoDTO[] itemInfos) { + super(); + this.itemInfos = itemInfos; + } + + public ShoppingBasketInfoDTO() { + // JSON + } + + + + /** + * @return the itemInfos + */ + public ItemInfoDTO[] getItemInfos() { + return itemInfos; + } + + /** + * @param itemInfos the itemInfos to set + */ + public void setItemInfos(ItemInfoDTO[] itemInfos) { + this.itemInfos = itemInfos; + } + + + + /** + * @return the plugin + */ + public String getPlugin() { + return plugin; + } + + /** + * @param plugin the plugin to set + */ + public void setPlugin(String plugin) { + this.plugin = plugin; + } + + /** + * @return the action + */ + public String getAction() { + return action; + } + + /** + * @param action the action to set + */ + public void setAction(String action) { + this.action = action; + } + + + + public static class ItemInfoDTO { + String exerciseIDs; + String gitLabURls; + + public ItemInfoDTO(String exerciseIDs, String gitLabURls) { + super(); + this.exerciseIDs = exerciseIDs; + this.gitLabURls = gitLabURls; + } + + public ItemInfoDTO() { + // JSON + } + /** + * @return the exerciseIDs + */ + public String getExerciseIDs() { + return exerciseIDs; + } + /** + * @param exerciseIDs the exerciseIDs to set + */ + public void setExerciseIDs(String exerciseIDs) { + this.exerciseIDs = exerciseIDs; + } + /** + * @return the gitLabURls + */ + public String getGitLabURls() { + return gitLabURls; + } + /** + * @param gitLabURls the gitLabURls to set + */ + public void setGitLabURls(String gitLabURls) { + this.gitLabURls = gitLabURls; + } + } + } + private final Logger log = LoggerFactory.getLogger(ShoppingBasketService.class); @@ -28,5 +183,27 @@ public class ShoppingBasketService { final ShoppingBasket shoppingBasket = new ShoppingBasket(userInfo, new ExerciseInfo[] {exerciseInfo}); return shoppingBasket; } + + LoadingCache<String, ShoppingBasketInfoDTO> basketCache = CacheBuilder.newBuilder() + .maximumSize(10000) + .expireAfterWrite(10, TimeUnit.MINUTES) + .build( + new CacheLoader<String, ShoppingBasketInfoDTO>() { + public ShoppingBasketInfoDTO load(String key) { + return new ShoppingBasketInfoDTO(); + } + }); + public ShoppingBasketRedirectInfoDTO getRedirectInfo(ShoppingBasketInfoDTO basket, String baseURL) { + UUID random = UUID.randomUUID(); + basketCache.put(random.toString(), basket); + + ShoppingBasketRedirectInfoDTO result = new ShoppingBasketRedirectInfoDTO(); + result.setRedirectURL(pluginManagementService.getRedirectURL(basket.getPlugin(), basket.getAction())); + result.setShoppingBasketToken(random.toString()); + result.setCallBackURL(baseURL); + + return result; + + } } diff --git a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java index 39d6f55af..05b13560e 100644 --- a/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java +++ b/src/main/java/at/ac/uibk/gitsearch/service/dto/SearchResultsDTO.java @@ -24,6 +24,61 @@ public class SearchResultsDTO { return externalName; } } + + public static class PluginActionInfo { + String plugin; + String action; + String commandName; + + public PluginActionInfo(String plugin, String action, String commandName) { + super(); + this.plugin = plugin; + this.action = action; + this.commandName = commandName; + } + + public PluginActionInfo() { + // JSON + } + /** + * @return the plugin + */ + public String getPlugin() { + return plugin; + } + /** + * @param plugin the plugin to set + */ + public void setPlugin(String plugin) { + this.plugin = plugin; + } + /** + * @return the action + */ + public String getAction() { + return action; + } + /** + * @param action the action to set + */ + public void setAction(String action) { + this.action = action; + } + /** + * @return the commandName + */ + public String getCommandName() { + return commandName; + } + /** + * @param commandName the commandName to set + */ + public void setCommandName(String commandName) { + this.commandName = commandName; + } + + + } public static class Person { private String name; @@ -195,6 +250,8 @@ public class SearchResultsDTO { private String[] requires; private String image; + + private PluginActionInfo[] supportedActions; public String getIdentifier() { return identifier; @@ -406,6 +463,20 @@ public class SearchResultsDTO { this.project = project; } + /** + * @return the supportedActions + */ + public PluginActionInfo[] getSupportedActions() { + return supportedActions; + } + + /** + * @param supportedActions the supportedActions to set + */ + public void setSupportedActions(PluginActionInfo[] supportedActions) { + this.supportedActions = supportedActions; + } + /** * clone constructor * diff --git a/src/main/java/at/ac/uibk/gitsearch/web/rest/PluginInterfaceResource.java b/src/main/java/at/ac/uibk/gitsearch/web/rest/PluginInterfaceResource.java index 7392267b4..330b71d22 100644 --- a/src/main/java/at/ac/uibk/gitsearch/web/rest/PluginInterfaceResource.java +++ b/src/main/java/at/ac/uibk/gitsearch/web/rest/PluginInterfaceResource.java @@ -4,17 +4,23 @@ import java.io.IOException; import javax.websocket.server.PathParam; +import org.codeability.sharing.plugins.api.ShoppingBasket; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import at.ac.uibk.gitsearch.es.model.DocumentInfo; import at.ac.uibk.gitsearch.service.ShoppingBasketService; -import at.ac.uibk.gitsearch.service.ShoppingBasketService.ShoppingBasket; +import at.ac.uibk.gitsearch.service.ShoppingBasketService.ShoppingBasketInfoDTO; +import at.ac.uibk.gitsearch.service.ShoppingBasketService.ShoppingBasketRedirectInfoDTO; +import at.ac.uibk.gitsearch.service.dto.SearchInputDTO; /** * REST controller for managing {@link DocumentInfo}. @@ -28,6 +34,12 @@ public class PluginInterfaceResource { @Autowired private ShoppingBasketService basketService; + + @PostMapping("/shoppingBasket/getPluginRedirectInfos") + public ShoppingBasketRedirectInfoDTO getRedirectInfos(@RequestBody ShoppingBasketInfoDTO basketInfo) { + return basketService.getRedirectInfo(basketInfo, "http://..."); + } + /** * {@code SEARCH /search/page-details} : search for the searchResults corresponding * to the query. @@ -36,8 +48,8 @@ public class PluginInterfaceResource { * @return the result of the search. */ @GetMapping("/pluginIF/getBasket/{basketToken}") - public ShoppingBasket - searchPageDetails(@PathParam("basketToken") String basketToken) throws IOException { + public ShoppingBasket searchPageDetails( + @PathParam("basketToken") String basketToken) throws IOException { log.debug("REST request for basket {}", basketToken); return basketService.getBasket(basketToken); } -- GitLab