package eu.dnetlib.functionality.modular.ui.is; import java.io.IOException; import java.io.StringReader; import java.net.HttpURLConnection; import java.net.URL; import java.util.*; import javax.annotation.Resource; import javax.servlet.ServletOutputStream; import javax.servlet.ServletResponse; import javax.xml.transform.dom.DOMResult; import javax.xml.xpath.XPathFactory; import com.google.common.base.Splitter; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpDocumentNotFoundException; import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpException; import eu.dnetlib.enabling.is.lookup.rmi.ISLookUpService; import eu.dnetlib.enabling.is.registry.rmi.ISRegistryService; import eu.dnetlib.enabling.is.sn.SubscriptionRegistry; import eu.dnetlib.enabling.is.sn.resourcestate.ResourceStateSubscription; import eu.dnetlib.enabling.locators.UniqueServiceLocator; import eu.dnetlib.functionality.modular.ui.AbstractAjaxController; import eu.dnetlib.functionality.modular.ui.is.bulk.ProfileImporter; import eu.dnetlib.functionality.modular.ui.is.objects.*; import eu.dnetlib.functionality.modular.ui.is.objects.ServiceDesc.ServiceStatus; import eu.dnetlib.miscutils.datetime.DateUtils; import org.apache.commons.io.IOUtils; import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.dom4j.Document; import org.dom4j.io.SAXReader; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.ResponseBody; @Controller public class InformationServiceInternalController extends AbstractAjaxController { @Resource private UniqueServiceLocator serviceLocator; @Resource(name = "modularUiProfileImporter") private ProfileImporter profileImporter; /** * is sn subscription registries. */ @Resource(name = "issResourceStateNotificationRegistry") private transient SubscriptionRegistry registry; private static final Log log = LogFactory.getLog(InformationServiceInternalController.class); @RequestMapping("/ui/is/xquery.do") public @ResponseBody List query(@RequestParam(value = "query", required = true) final String query) throws Exception { log.debug("Executing xquery: " + query); return serviceLocator.getService(ISLookUpService.class).quickSearchProfile(query); } @RequestMapping("/ui/is/listSchemas.do") public @ResponseBody List listSchemas() throws Exception { return serviceLocator.getService(ISLookUpService.class).listResourceTypes(); } @RequestMapping("/ui/is/getSchema.do") public @ResponseBody String getSchema(@RequestParam(value = "name", required = true) final String name) throws Exception { return serviceLocator.getService(ISLookUpService.class).getResourceTypeSchema(name); } @RequestMapping("/ui/is/listCollections.do") public @ResponseBody List listCollections() throws Exception { final String xquery = "for $kind in xmldb:get-child-collections('/db/DRIVER') " + "for $type in xmldb:get-child-collections(concat('/db/DRIVER/', $kind)) " + "return concat ($kind, ' @@@ ', $type, ' @@@ ', count(xmldb:get-child-resources(concat('/db/DRIVER/', $kind, '/', $type))))"; final Map map = Maps.newHashMap(); for (String s : serviceLocator.getService(ISLookUpService.class).quickSearchProfile(xquery)) { final String[] arr = s.split("@@@"); final String kind = arr[0].trim(); final String type = arr[1].trim(); final int size = NumberUtils.toInt(arr[2].trim(), 0); if (!map.containsKey(kind)) { map.put(kind, new CollectionDesc(kind)); } map.get(kind).addType(type, size); } final List res = Lists.newArrayList(map.values()); for (CollectionDesc d : res) { Collections.sort(d.getTypes()); } Collections.sort(res); return res; } @RequestMapping("/ui/is/listProfiles.do") public @ResponseBody List listProfiles(@RequestParam(value = "kind", required = true) final String kind, @RequestParam(value = "type", required = true) final String type) throws Exception { final String collName = "/db/DRIVER/" + kind + "/" + type; final String xquery = "distinct-values(for $x in collection('" + collName + "') return $x//RESOURCE_IDENTIFIER/@value/string())"; final List res = serviceLocator.getService(ISLookUpService.class).quickSearchProfile(xquery); Collections.sort(res); return res; } @RequestMapping("/ui/is/getProfile.do") public @ResponseBody String getProfiles(@RequestParam(value = "id", required = true) final String id) throws Exception { return serviceLocator.getService(ISLookUpService.class).getResourceProfile(id); } @RequestMapping("/ui/is/registerProfile.do") public @ResponseBody String registerProfile(@RequestParam(value = "profile", required = true) final String profile) throws Exception { return serviceLocator.getService(ISRegistryService.class).registerProfile(profile); } @RequestMapping("/ui/is/updateProfile.do") public @ResponseBody String updateProfile(@RequestParam(value = "profile", required = true) final String profile) throws Exception { final SAXReader reader = new SAXReader(); final Document doc = reader.read(new StringReader(profile)); final String id = doc.valueOf("//RESOURCE_IDENTIFIER/@value"); final String type = doc.valueOf("//RESOURCE_TYPE/@value"); if (StringUtils.isEmpty(id)) { throw new Exception("RESOURCE_IDENTIFIER is empty"); } else if (StringUtils.isEmpty(type)) { throw new Exception("RESOURCE_TYPE is empty"); } else if (serviceLocator.getService(ISRegistryService.class).updateProfile(id, profile, type)) { return id; } else { throw new Exception("Profile not updated"); } } @RequestMapping("/ui/is/deleteProfile.do") public @ResponseBody boolean deleteProfile(@RequestParam(value = "id", required = true) final String id) throws Exception { return serviceLocator.getService(ISRegistryService.class).deleteProfile(id); } @RequestMapping("/ui/is/import.do") public @ResponseBody Map importProfiles( @RequestParam(value = "path", required = true) final String path, @RequestParam(value = "profiles", required = true) final boolean profiles, @RequestParam(value = "schemas", required = true) final boolean schemas) throws Exception { log.info("importing profiles/schemas from " + path); final Map res = Maps.newHashMap(); if (schemas) { res.putAll(profileImporter.importSchemas(path + "/**/*.xsd")); } if (profiles) { res.putAll(profileImporter.importProfiles(path + "/**/*.xml")); } return res; } @RequestMapping("/ui/is/listBlackboards.do") public @ResponseBody List listBlackboards() throws Exception { final List list = Lists.newArrayList(); final SAXReader reader = new SAXReader(); for (String xml : serviceLocator .getService(ISLookUpService.class) .quickSearchProfile( "for $x in collection('/db/DRIVER/ServiceResources')//MESSAGE return {$x/../../..//RESOURCE_TYPE}{$x/../../..//RESOURCE_IDENTIFIER}{$x}")) { final BlackboardMessage info = new BlackboardMessage(); final Document doc = reader.read(new StringReader(xml)); info.setProfId(doc.valueOf(".//RESOURCE_IDENTIFIER/@value")); info.setMessageId(doc.valueOf(".//@id")); info.setResourceType(doc.valueOf(".//RESOURCE_TYPE/@value")); info.setAction(doc.valueOf(".//ACTION")); info.setDate(doc.valueOf(".//@date")); info.setActionStatus(doc.valueOf(".//ACTION_STATUS")); info.setError(doc.valueOf(".//PARAMETER[@name='error']/@value")); list.add(info); } return list; } @RequestMapping("/ui/is/getMetaWfIdForFamily.do") public @ResponseBody Map getMetaWfId(@RequestParam(value = "family", required = true) final String family) throws ISLookUpException { final String xq = "for $x in collection('/db/DRIVER/WorkflowDSResources/WorkflowDSResourceType') " + "where $x//WORKFLOW_FAMILY='" + family + "' " + "return concat($x//RESOURCE_IDENTIFIER/@value, ' @@@ ', $x//WORKFLOW_NAME/@menuSection)"; final Map map = Maps.newHashMap(); try { final String[] arr = serviceLocator.getService(ISLookUpService.class).getResourceProfileByQuery(xq).split("@@@"); map.put("id", arr[0].trim()); map.put("section", arr[1].trim()); } catch (ISLookUpDocumentNotFoundException e) { map.put("id", ""); map.put("section", ""); } map.put("family", family); return map; } @RequestMapping("/ui/is/listServices.do") public @ResponseBody Collection listServices() throws Exception { final String xq = IOUtils.toString(getClass().getResourceAsStream("/eu/dnetlib/functionality/modular/xquery/listServices.xquery")); final List list = Lists.newArrayList(); final SAXReader reader = new SAXReader(); for (String s : serviceLocator.getService(ISLookUpService.class).quickSearchProfile(xq)) { final Document doc = reader.read(new StringReader(s)); final String id = doc.valueOf("/service/id").trim(); final String name = doc.valueOf("/service/name").trim(); final String wsdl = doc.valueOf("/service/wsdl").trim(); list.add(new ServiceDesc(id, name, wsdl)); } final XPathFactory xpathFactory = XPathFactory.newInstance(); for (ResourceStateSubscription sub : registry.listSubscriptions()) { boolean notFound = true; final DOMResult result = new DOMResult(); // NOPMD sub.getSubscriberAsEpr().writeTo(result); final String wsdl = xpathFactory.newXPath().evaluate("//*[local-name() = 'Address']", result.getNode()) + "?wsdl"; for (ServiceDesc s : list) { if (s.getWsdl().equalsIgnoreCase(wsdl)) { s.getSubscriptions().add(new SubscriptionDesc(sub)); notFound = false; } } if (notFound) { final ServiceDesc desc = new ServiceDesc("", "", wsdl); desc.getSubscriptions().add(new SubscriptionDesc(sub)); desc.setStatus(ServiceStatus.MISSING); list.add(desc); } } final Map map = Maps.newHashMap(); for (ServiceDesc s : list) { final URL url = new URL(s.getWsdl()); final String host = url.getHost(); final int port = url.getPort(); final String context = Iterables.getFirst(Splitter.on("/").omitEmptyStrings().split(url.getPath()), ""); final String tmpKey = host + "@@@" + port + "@@@" + context; if (!map.containsKey(tmpKey)) { map.put(tmpKey, new ServiceGrouperDesc(host, port, context, new ArrayList())); } map.get(tmpKey).getServices().add(s); } return map.values(); } @RequestMapping("/ui/is/ping.do") public @ResponseBody long pingUrl(@RequestParam(value = "url", required = true) final String url, @RequestParam(value = "timeout", required = true) final int timeout) throws IOException { final long start = DateUtils.now(); final HttpURLConnection urlConn = (HttpURLConnection) new URL(url).openConnection(); urlConn.setConnectTimeout(timeout); urlConn.setReadTimeout(timeout); if (urlConn.getResponseCode() == HttpURLConnection.HTTP_OK) { return DateUtils.now() - start; } else { throw new IllegalArgumentException("Invalid Url"); } } public void sendXML(final ServletResponse response, final String xml) throws IOException { response.setContentType("text/xml"); final ServletOutputStream out = response.getOutputStream(); IOUtils.copy(new StringReader(xml), out); out.flush(); out.close(); } }