package org.bygle.endpoint.managing; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URISyntaxException; import java.net.URLEncoder; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; import org.bygle.bean.RdfClasses; import org.bygle.bean.RecordTypes; import org.bygle.bean.Records; import org.bygle.db.services.BygleService; import org.bygle.endpoint.managing.utils.RelationsContainer; import org.bygle.service.LDPService; import org.bygle.service.RelationsService; import org.bygle.service.bean.Content; import org.bygle.utils.BygleSystemUtils; import org.bygle.xml.XMLReader; import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Restrictions; import org.openrdf.repository.RepositoryException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; import virtuoso.jena.driver.VirtGraph; import virtuoso.jena.driver.VirtuosoUpdateFactory; import virtuoso.jena.driver.VirtuosoUpdateRequest; import com.hp.hpl.jena.graph.Node; import com.hp.hpl.jena.graph.Triple; import com.hp.hpl.jena.rdf.model.Model; import com.hp.hpl.jena.rdf.model.ModelFactory; import com.hp.hpl.jena.rdf.model.ResIterator; import com.hp.hpl.jena.rdf.model.Resource; import com.hp.hpl.jena.rdf.model.SimpleSelector; import com.hp.hpl.jena.rdf.model.Statement; import com.hp.hpl.jena.rdf.model.StmtIterator; import com.hp.hpl.jena.util.FileManager; public class VirtuosoEndPointManager extends EndPointManager { @Autowired RelationsService relationsService; @Autowired LDPService ldpService; @Autowired BygleService bygleService; private int port = 1111; private String username, password, defaultGraph, server; Map<String, VirtGraph> endpointsMap = new HashMap<String, VirtGraph>(); public VirtuosoEndPointManager() { } public void createConnection() throws RepositoryException { } public void closeConnection() { for (String chiave : endpointsMap.keySet()) { if (endpointsMap.get(chiave) != null && !endpointsMap.get(chiave).isClosed()) { try { endpointsMap.get(chiave).close(); } catch (Exception e) { System.err.println("connection already closed (" + chiave + ")? " + e.getMessage()); } } } } @Override public void publishRecord(byte[] rdf, String rdfAbout,String host) throws Exception { System.out.println("VirtuosoEndPointManager.publishRecord()"); if (!endpointsMap.containsKey(server + "+" + defaultGraph)) { System.out.println("connecting to " + server + " for graph " + defaultGraph); endpointsMap.put(server + "+" + defaultGraph, new VirtGraph(defaultGraph, "jdbc:virtuoso://" + server + ":" + port, username, password)); System.out.println("connected!"); } VirtGraph virtGraph = endpointsMap.get(server + "+" + defaultGraph); Model m = ModelFactory.createDefaultModel(); m.read(new ByteArrayInputStream(rdf), ""); Map<String, Node> sub = new HashMap<String, Node>(); for (StmtIterator i = m.listStatements(); i.hasNext();) { Statement s = (Statement) i.next(); Triple a = s.asTriple(); if (a.getObject().isBlank()) { String obs = a.getObject().getBlankNodeLabel(); if (!sub.containsKey(obs)) { sub.put(obs, Node.createURI("nodeID://b" + System.nanoTime())); } } if (a.getSubject().isBlank()) { String obs = a.getSubject().getBlankNodeLabel(); if (!sub.containsKey(obs)) { sub.put(obs, Node.createURI("nodeID://b" + System.nanoTime())); } } } for (StmtIterator i = m.listStatements(); i.hasNext();) { Statement s = (Statement) i.next(); Triple a = s.asTriple(); if (a.getObject().isBlank()) { String obs = a.getObject().getBlankNodeLabel(); a = Triple.create(a.getSubject(), a.getPredicate(), sub.get(obs)); } if (a.getSubject().isBlank()) { String obs = a.getSubject().getBlankNodeLabel(); a = Triple.create(sub.get(obs), a.getPredicate(), a.getObject()); } Node o = a.getObject(); if (o.isLiteral() && o.getLiteralDatatypeURI() != null) { String value = o.getLiteralLexicalForm(); value = value.replaceAll("\"", "\\\\\"").replaceAll("\n", "\\\\n"); String str = "INSERT INTO GRAPH <" + virtGraph.getGraphName() + "> { <" + a.getSubject() + "> <" + a.getPredicate() + "> \"" + value + "\"^^<" + o.getLiteralDatatypeURI() + ">. }"; VirtuosoUpdateRequest vur = VirtuosoUpdateFactory.create(str, virtGraph); vur.exec(); } else { virtGraph.add(a); } } } @Override public void dePublishRecord(byte[] rdf, String rdfAbout, String host) { System.out.println("VirtuosoEndPointManager.dePublishRecord()"); System.out.println("removing " + rdfAbout); if (!endpointsMap.containsKey(server + "+" + defaultGraph)) { System.out.println("connecting to " + server + " for graph " + defaultGraph); endpointsMap.put(server + "+" + defaultGraph, new VirtGraph(defaultGraph, "jdbc:virtuoso://" + server + ":" + port, username, password)); System.out.println("connected!"); } VirtGraph virtGraph = endpointsMap.get(server + "+" + defaultGraph); System.out.println("dePublishRecord from " + virtGraph.getGraphName() + " -- URI -- " + rdfAbout); StringBuilder query = new StringBuilder(); query.append(" DELETE FROM GRAPH <" + virtGraph.getGraphName() + "> {?bn ?a ?b} WHERE {"); query.append("{<" + host + rdfAbout + "> ?p ?o"); query.append(". FILTER(isBlank(?o))"); query.append(". ?o ?c ?s"); query.append(". FILTER(isBlank(?s))"); query.append(". ?s ?d ?bn"); query.append(". FILTER(isBlank(?bn))}"); query.append("UNION{"); query.append("<" + host + rdfAbout + "> ?p ?o"); query.append(". FILTER(isBlank(?o))"); query.append(". ?o ?c ?bn"); query.append(". FILTER(isBlank(?bn))}"); query.append("UNION{"); query.append(" <" + host + rdfAbout + "> ?p ?bn"); query.append(". FILTER(isBlank(?bn))"); query.append("} ?bn ?a ?b}"); VirtuosoUpdateRequest vur = VirtuosoUpdateFactory.create(query.toString(), virtGraph); vur.exec(); String deleteRequest = "delete from graph <" + virtGraph.getGraphName() + "> {?s ?p ?o.} FROM <" + virtGraph.getGraphName() + "> WHERE {?s ?p ?o. FILTER(?s = <" + (rdfAbout.startsWith("http://") ? rdfAbout : host + rdfAbout) + ">)}"; System.out.println("[bygle - info] deleteing " + deleteRequest); vur = VirtuosoUpdateFactory.create(deleteRequest, virtGraph); vur.exec(); } @Override public void rePublishRecord(byte[] rdf, String rdfAbout,String host) throws Exception { System.out.println("VirtuosoEndPointManager.rePublishRecord()"); dePublishRecord(rdf, rdfAbout, host); publishRecord(rdf, rdfAbout, host); } @Override public void resetEndpoint() throws Exception { System.out.println("VirtuosoEndPointManager.resetEndpoint()"); if (!endpointsMap.containsKey(server + "+" + defaultGraph)) { System.out.println("connecting to " + server + " for graph " + defaultGraph); endpointsMap.put(server + "+" + defaultGraph, new VirtGraph(defaultGraph, "jdbc:virtuoso://" + server + ":" + port, username, password)); System.out.println("connected!"); } VirtGraph virtGraph = endpointsMap.get(server + "+" + defaultDomain); if (virtGraph != null) virtGraph.clear(); } @Override public void dropEndpoint() throws Exception { System.out.println("VirtuosoEndPointManager.dropEndpoint()"); resetEndpoint(); } @Override public void executeImport() throws Exception { super.executeImport(); // WebApplicationContext springContext = // WebApplicationContextUtils.getWebApplicationContext(servletConext); // ldpService = (LDPService) springContext.getBean("ldpService"); // bygleService = (BygleService) springContext.getBean("bygleService"); // relationsService = (RelationsService) // springContext.getBean("relationsService"); File importDir = new File(importDirectory); if (importDir.list().length > 0) { List<RelationsContainer> addRelationsContainerList = new ArrayList<RelationsContainer>(); List<RelationsContainer> updateRelationsContainerList = new ArrayList<RelationsContainer>(); File[] importFiles = importDir.listFiles(); Model modelBase = ModelFactory.createDefaultModel(); // ldpService.addDefaultNamespaces(modelBase); System.out.println("VirtuosoEndPointManager.executeImport() reading files"); for (int i = 0; i < importFiles.length; i++) { if (importFiles[i].isFile()) { try { System.out.println("loading RDF " + importFiles[i].getAbsolutePath()); FileManager.get().readModel(modelBase, importFiles[i].getAbsolutePath()); } catch (Exception e) { // e.printStackTrace(); System.err.println("[bygle - error] importing " + e.getMessage()); FileUtils.moveFile(importFiles[i], new File(importFiles[i].getAbsolutePath().replaceAll("(.+)\\.(\\w+)$", "$1_error.$2"))); FileUtils.writeStringToFile(new File(importFiles[i].getAbsolutePath().replaceAll("(.+)\\.(\\w+)$", "$1_error.$2.log")), e.getMessage()); } } } ResIterator resources = modelBase.listSubjects(); System.out.println("VirtuosoEndPointManager.executeImport() starting import"); while (resources.hasNext()) { Resource resource = (Resource) resources.next(); if (!resource.isAnon()) { try { List<Statement> statementList = modelBase.listStatements(new SimpleSelector(resource, null, null, null)).toList(); Model modelResource = ModelFactory.createDefaultModel(); modelResource.setNsPrefixes(modelBase.getNsPrefixMap()); modelResource.add(statementList); addAnon(modelBase, modelResource, statementList); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); modelResource.write(byteArrayOutputStream, BygleSystemUtils.getWriter("application/rdf+xml-abbr")); // diego: // RDF/XML-ABBREV XMLReader xmlReader = new XMLReader(byteArrayOutputStream.toByteArray()); String rdfAbout = xmlReader.getNodeValue("/rdf:RDF/*/@rdf:about"); System.out.println("VirtuosoEndPointManager.executeImport() importing " + rdfAbout); List<?> nodeList = xmlReader.getNodeList("/rdf:RDF/*/*/@rdf:resource[not(ancestor::rdf:type)]"); Content content = ldpService.createContent(byteArrayOutputStream.toByteArray(), "application/rdf+xml", "application/rdf+xml", BygleSystemUtils.getStringProperty("endpoint.defaultDomain"), rdfAbout, null, null, true); RecordTypes recordTypes = (RecordTypes) bygleService.getObject(RecordTypes.class, content.getResourceType()); RdfClasses rdfClasses = getRdfClasses(content.getENTITY_TYPE(), rdfAbout); String md5ETag = DigestUtils.md5Hex(new String(byteArrayOutputStream.toByteArray())); DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Records.class); detachedCriteria.add(Restrictions.eq("rdfAbout", rdfAbout)); detachedCriteria.add(Restrictions.not(Restrictions.eq("etag", md5ETag))); detachedCriteria.add(Restrictions.eq("host", ldpService.getHostFromRdfAbout(rdfAbout))); List<?> recordsList = bygleService.getList(detachedCriteria); if (recordsList.size() > 0) { Records records = (Records) recordsList.get(0); byte[] oldRdf = records.getRdf(); records.setModifyDate(new Date()); records.setEtag(md5ETag); records.setRdf(byteArrayOutputStream.toByteArray()); bygleService.update(records); updateRelationsContainerList.add(new RelationsContainer(records.getIdRecord(), oldRdf)); relationsService.updateRelations(records, oldRdf); } else { detachedCriteria = DetachedCriteria.forClass(Records.class); detachedCriteria.add(Restrictions.eq("rdfAbout", rdfAbout)); detachedCriteria.add(Restrictions.eq("etag", md5ETag)); detachedCriteria.add(Restrictions.eq("host", ldpService.getHostFromRdfAbout(rdfAbout))); recordsList = bygleService.getList(detachedCriteria); if (recordsList.size() == 0) { Records records = new Records(recordTypes, rdfClasses, byteArrayOutputStream.toByteArray(), new Date(), null, rdfAbout, "application/rdf+xml", md5ETag, md5ETag, ldpService.getHostFromRdfAbout(rdfAbout)); bygleService.add(records); addRelationsContainerList.add(new RelationsContainer(records.getIdRecord(), nodeList)); } } } catch (Exception e) { } } } FileUtils.cleanDirectory(importDir); } } private void addAnon(Model modelBase, Model modelResource, List<Statement> statementList) { for (int i = 0; i < statementList.size(); i++) { Statement statement = statementList.get(i); if (statement.getObject().isAnon()) { List<Statement> newStatementList = modelBase.listStatements(new SimpleSelector(statement.getObject().asResource(), null, null, null)).toList(); modelResource.add(newStatementList); addAnon(modelBase, modelResource, newStatementList); } } } public synchronized RdfClasses getRdfClasses(Resource ENTITY_TYPE, String about) throws UnsupportedEncodingException, URISyntaxException { RdfClasses rdfClasses = null; if (ENTITY_TYPE != null) { DetachedCriteria detachedCriteria = DetachedCriteria.forClass(RdfClasses.class); detachedCriteria.add(Restrictions.eq("rdfType", ENTITY_TYPE.toString())); List<?> list = bygleService.getList(detachedCriteria); if (list.size() == 0) { try { java.net.URI className = new java.net.URI(URLEncoder.encode(ENTITY_TYPE.getModel().qnameFor(ENTITY_TYPE.getURI()), BygleSystemUtils.getStringProperty("default.encoding"))); rdfClasses = new RdfClasses(className.toString(), ENTITY_TYPE.getURI(), 1); } catch (Exception e) { rdfClasses = new RdfClasses("defaultResource", ENTITY_TYPE.getURI(), 1); } bygleService.add(rdfClasses); return rdfClasses; } else { rdfClasses = (RdfClasses) list.get(0); if (about.indexOf(ENTITY_TYPE.toString()) == -1) { rdfClasses.setCount(rdfClasses.getCount() + 1); bygleService.update(rdfClasses); } } } return rdfClasses; } public String getServer() { return server; } public void setServer(String server) { this.server = server; } public String getDefaultGraph() { return defaultGraph; } public void setDefaultGraph(String defaultGraph) { this.defaultGraph = defaultGraph; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } }