package eu.dnetlib.functionality.modular.ui.repositories; import java.io.StringReader; import java.util.Date; import java.util.List; import java.util.Map; import javax.annotation.Resource; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.exception.ExceptionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.annotation.CacheEvict; import org.springframework.cache.annotation.Cacheable; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Controller; import org.springframework.ui.ModelMap; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.ResponseStatus; import com.google.common.collect.Maps; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import eu.dnetlib.data.collector.rmi.CollectorService; import eu.dnetlib.data.collector.rmi.CollectorServiceException; import eu.dnetlib.data.collector.rmi.ProtocolParameterValue; import eu.dnetlib.enabling.datasources.common.Api; import eu.dnetlib.enabling.datasources.common.ApiParam; import eu.dnetlib.enabling.datasources.common.ApiParamImpl; import eu.dnetlib.enabling.datasources.common.BrowseTerm; import eu.dnetlib.enabling.datasources.common.Datasource; import eu.dnetlib.enabling.datasources.common.DsmException; import eu.dnetlib.enabling.datasources.common.Identity; import eu.dnetlib.enabling.datasources.common.LocalDatasourceManager; import eu.dnetlib.enabling.datasources.common.Organization; import eu.dnetlib.enabling.datasources.common.SearchApisEntry; import eu.dnetlib.enabling.datasources.common.SimpleDatasource; import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException; import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService; import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService; import eu.dnetlib.enabling.locators.UniqueServiceLocator; import eu.dnetlib.functionality.modular.ui.error.ErrorMessage; import eu.dnetlib.functionality.modular.ui.repositories.objects.RepoInterfaceEntry; import eu.dnetlib.functionality.modular.ui.workflows.objects.sections.WorkflowSectionGrouper; import eu.dnetlib.miscutils.functional.xml.ApplyXslt; import eu.dnetlib.msro.workflows.sarasvati.loader.WorkflowExecutor; import eu.dnetlib.msro.workflows.util.WorkflowsConstants; @Controller public class RepoInternalController { @Autowired private LocalDatasourceManager, Api> dsManager; @Resource private UniqueServiceLocator serviceLocator; @Resource private WorkflowSectionGrouper workflowSectionGrouper; @Resource private WorkflowExecutor workflowExecutor; @Resource private RepoUIUtils repoUIUtils; private static final Log log = LogFactory.getLog(RepoInternalController.class); @RequestMapping(value = "/ui/browseRepoField.do") public @ResponseBody List browseRepoField(@RequestParam(value = "field", required = true) final String field) throws Exception { return dsManager.browseField(field); } @Cacheable(cacheNames = "repoUIJsonCache", key = "#param, #value", condition = "#refresh == false") @RequestMapping(value = "/ui/listApis.do") public @ResponseBody List listApis( @RequestParam(value = "param", required = true) final String param, @RequestParam(value = "value", required = true) final String value, @RequestParam(value = "refresh", required = false) final String refresh) throws Exception { return dsManager.searchApis(param, value); } @RequestMapping(value = "/ui/listRepositories.json") public @ResponseBody List listRepositories(@RequestParam(value = "type", required = true) final String type) throws Exception { return dsManager.searchDatasourcesByType(type); } @CacheEvict("repoUIJsonCache") @RequestMapping(value = "/ui/validateRepo.do") public @ResponseBody String listRepositories(@RequestParam(value = "id", required = true) final String id, @RequestParam(value = "b", required = true) final boolean b) throws Exception { final String query = "count(/*[.//RESOURCE_TYPE/@value='MetaWorkflowDSResourceType' and .//DATAPROVIDER/@id='" + id + "'])"; if (!b && Integer.parseInt(serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(query)) > 0) { throw new Exception("Repo " + id + " can be invalidated: it is related to some metawfs"); } final String newId = b ? serviceLocator.getService(ISRegistryService.class).validateProfile(id) : serviceLocator.getService(ISRegistryService.class).invalidateProfile(id); return newId; } @RequestMapping(value = "/ui/getRepoDetails.do") public void getRepoDetails(final HttpServletResponse response, @RequestParam(value = "id", required = true) final String id) throws Exception { String profile; try { profile = serviceLocator.getService(ISLookUpService.class).getResourceProfile(id); } catch (final ISLookUpDocumentNotFoundException e) { profile = serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery( "collection('/db/DRIVER/RepositoryServiceResources/RepositoryServiceResourceType')/*[.//DATASOURCE_ORIGINAL_ID='" + id + "']"); } final ApplyXslt xslt = new ApplyXslt(IOUtils.toString(getClass().getResourceAsStream( "/eu/dnetlib/functionality/modular/ui/repositories/xslt/repoDetails.xslt"))); IOUtils.copy(new StringReader(xslt.evaluate(profile)), response.getOutputStream()); } @RequestMapping("/ui/repoMetaWf.new") public @ResponseBody String newDataProviderWorkflow(@RequestParam(value = "id", required = true) final String repoId, @RequestParam(value = "name", required = true) final String repoName, @RequestParam(value = "iface", required = true) final String ifaceId, @RequestParam(value = "wf", required = true) final String wfId) throws Exception { final Map params = Maps.newHashMap(); params.put(WorkflowsConstants.DATAPROVIDER_ID, repoId); params.put(WorkflowsConstants.DATAPROVIDER_NAME, repoName); params.put(WorkflowsConstants.DATAPROVIDER_INTERFACE, ifaceId); return workflowExecutor.startProcess(wfId, params); } @RequestMapping("/ui/repoMetaWf.destroy") public @ResponseBody String destroyDataProviderWorkflow(@RequestParam(value = "destroyWf", required = true) final String destroyWfId) throws Exception { return workflowExecutor.startProcess(destroyWfId, null); } @RequestMapping("/ui/repoApi.get") public @ResponseBody RepoInterfaceEntry getRepoApi(@RequestParam(value = "repoId", required = true) final String repoId, @RequestParam(value = "ifaceId", required = true) final String ifaceId) throws Exception { try { return repoUIUtils.getApi(repoId, ifaceId); } catch (ISLookUpDocumentNotFoundException e) { log.warn(String.format("the Interface '%s' is not available for repository '%s', try to sync DB and profiles via the DatasourceManager", ifaceId, repoId)); dsManager.setActive(repoId, ifaceId, dsManager.isActive(repoId, ifaceId)); return repoUIUtils.getApi(repoId, ifaceId); } } @RequestMapping("/ui/repoApi.update") public @ResponseBody boolean updateRepoApi( @RequestParam(value = "id", required = true) final String repoId, @RequestParam(value = "iface", required = true) final String ifaceId, @RequestParam(value = "accessParams", required = false) final String accessParamsJson, @RequestParam(value = "mdIdPath", required = false) final String mdIdPath) throws Exception { if (!StringUtils.isEmpty(accessParamsJson)) { final Map params = new Gson().fromJson(accessParamsJson, new TypeToken>() {}.getType()); final String baseUrl = params.remove("baseUrl"); dsManager.updateApiDetails(repoId, ifaceId, mdIdPath, baseUrl, params); } return true; } @RequestMapping("/ui/repoApi.delete") public @ResponseBody boolean updateRepoApi( @RequestParam(value = "repo", required = true) final String repoId, @RequestParam(value = "iface", required = true) final String ifaceId) throws Exception { dsManager.deleteApi(repoId, ifaceId); return true; } @CacheEvict("repoUIJsonCache") @RequestMapping("/ui/repoApiCompliance.update") public @ResponseBody boolean updateRepoApiCompliance(@RequestParam(value = "id", required = true) final String repoId, @RequestParam(value = "iface", required = true) final String ifaceId, @RequestParam(value = "compliance", required = true) final String compliance) throws Exception { log.debug("SET COMPLIANCE TO " + compliance); dsManager.updateCompliance(repoId, ifaceId, compliance, true); return true; } @CacheEvict("repoUIJsonCache") @RequestMapping("/ui/repoApiCompliance.reset") public @ResponseBody boolean resetRepoApiCompliance(@RequestParam(value = "id", required = true) final String repoId, @RequestParam(value = "iface", required = true) final String ifaceId) throws Exception { log.debug("RESET COMPLIANCE"); dsManager.updateCompliance(repoId, ifaceId, null, true); return true; } @RequestMapping("/ui/repos/repoApi.html") public void resetRepoApiCompliance(final ModelMap map) throws Exception {} @RequestMapping("/ui/repoApi.new") public @ResponseBody boolean addRepoApi(@RequestParam(value = "repoId", required = true) final String repoId, @RequestParam(value = "iface", required = true) final String ifaceJson) throws DsmException { final Api iface = new Gson().fromJson(ifaceJson, new TypeToken>() {}.getType()); iface.setDatasource(repoId); log.info("Adding api " + iface.getId() + " to repository " + repoId); dsManager.addApi(iface); return true; } @RequestMapping("/ui/repo.new") public @ResponseBody boolean addRepoApi(@RequestParam(value = "repo", required = true) final String repoJson) throws DsmException { final Datasource, Identity> ds = new Gson().fromJson(repoJson, new TypeToken, Identity>>() {}.getType()); final Date now = new Date(); ds.setDateofcollection(new java.sql.Date(now.getTime())); if (StringUtils.isBlank(ds.getEnglishname())) { ds.setEnglishname(ds.getOfficialname()); } log.info("Adding datasource " + ds.getId() + " - name " + ds.getOfficialname()); dsManager.saveDs(ds); return true; } @RequestMapping("/ui/listValidValuesForParam.do") public @ResponseBody List listValidValuesForParam( @RequestParam(value = "protocol", required = true) final String protocol, @RequestParam(value = "param", required = true) final String param, @RequestParam(value = "baseUrl", required = true) final String baseUrl) throws CollectorServiceException { return serviceLocator.getService(CollectorService.class).listValidValuesForParam(protocol, baseUrl, param, null); } @ExceptionHandler(Exception.class) @ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR) public @ResponseBody ErrorMessage handleException(final HttpServletRequest req, final Exception e) { log.error("Error processing " + req.getRequestURI(), e); return new ErrorMessage(e.getMessage(), ExceptionUtils.getStackTrace(e)); } }