blob: 14b006ed231301f689033b150893794844e88290 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.clerezza.rdf.storage.sparql
import org.osgi.service.component.ComponentContext
import java.io.IOException
import java.net.{ HttpURLConnection, URL }
import org.apache.clerezza.rdf.core.serializedform.SupportedFormat
import org.apache.clerezza.rdf.core.serializedform.Parser
import java.security.PrivilegedActionException
import org.slf4j.scala._
import org.apache.clerezza.rdf.core.access._
import org.apache.clerezza.rdf.core.impl.AbstractMGraph
import org.apache.clerezza.rdf.core._
import scala.collection.JavaConversions.asScalaSet
import java.util.Collection
import java.util.Collections
import org.apache.felix.scr.annotations.Component
import org.apache.felix.scr.annotations.Service
import org.apache.felix.scr.annotations.Property
import java.net.URLEncoder
import org.apache.clerezza.rdf.core.impl.TripleImpl
import org.apache.clerezza.rdf.ontologies.RDF
/**
* The Web Proxy Service enables applications to request remote (and local) graphs.
* It keeps cached version of the remote graphs in store for faster delivery.
*
*/
@Component
@Service(Array(classOf[WeightedTcProvider]))
class SparqlStorageProvider extends WeightedTcProvider with Logging {
final val queryEndpointKey = "query-endpoint"
@Property(name = queryEndpointKey, value = Array("http://localhost:3030/ds/query"))
private var queryEndpoint: String = _
final val updateEndpointKey = "update-endpoint"
@Property(name = updateEndpointKey, value = Array("http://localhost:3030/ds/update"))
private var updateEndpoint: String = _
final val metaGraphName = new UriRef("urn:x-internal:/meta")
final val mGraphClass = new UriRef("http://clerezza.apache.org/ontologies/storage#MGraph")
/**OSGI method, called on activation */
protected def activate(context: ComponentContext) = {
queryEndpoint = context.getProperties.get(queryEndpointKey).toString
updateEndpoint = context.getProperties.get(updateEndpointKey).toString
}
private var parser: Parser = null
protected def bindParser(p: Parser) = {
parser = p
}
protected def unbindParser(p: Parser) = {
parser = null
}
def getWeight: Int = {
return 20000
}
def getMGraph(name: UriRef): MGraph = {
checkMGraphExists(name)
getMGraphNoExistenceCheck(name)
}
/**
* throws NoSuchEntity if not existing
*/
protected def checkMGraphExists(name: UriRef) {
val metaGraph = getMGraphNoExistenceCheck(metaGraphName)
if (!metaGraph.contains(new TripleImpl(name, RDF.`type`, mGraphClass))) {
throw new NoSuchEntityException(name)
}
}
protected def getMGraphNoExistenceCheck(name: UriRef): MGraph = {
return new AbstractMGraph() {
protected def performFilter(subject: NonLiteral, predicate: UriRef, obj: Resource): java.util.Iterator[Triple] = {
def ask = {
//TODO ask query
true
}
val vars = new collection.mutable.ListBuffer[Char]
if (subject == null) vars += 's'
if (predicate == null) vars += 'p'
if (obj == null) vars += 'o'
if (vars.isEmpty() && ask()) {
Collections.singletonList(new TripleImpl(subject, predicate, obj)).iterator()
} else {
val vs = vars.foldLeft[String]("")(((s,v) => s+" ?"+v+" "))
val query = "SELECT "+vs+" WHERE {" + SparqlStorageProvider.tpEncode(subject) +
" " + SparqlStorageProvider.tpEncode(predicate) + " " + SparqlStorageProvider.tpEncode(obj) + " } "
val url = new URL(queryEndpoint)
val con = url.openConnection().asInstanceOf[HttpURLConnection]
//not sure
System.out.println("DEBUG: doing output...")
con.setDoOutput(true)
con.setRequestMethod("POST")
val out = con.getOutputStream()
System.out.println("update: " + update)
out.write(("update=" + URLEncoder.encode(update)).getBytes())
val err = con.getErrorStream()
if (err != null) {
var che = err.read
while (che != -1) {
System.out.write(che)
che = err.read
}
} else {
val in = con.getInputStream()
var ch = in.read
while (ch != -1) {
System.out.write(ch)
ch = in.read
}
}
System.out.flush
Collections.emptyList[Triple]().iterator()
}
}
override def add(triple: Triple) = {
val update = "INSERT DATA { GRAPH " + name + " {" + SparqlStorageProvider.tpEncode(triple.getSubject) +
" " + SparqlStorageProvider.tpEncode(triple.getPredicate) + " " + SparqlStorageProvider.tpEncode(triple.getObject) + " } }"
performUpdate(update)
true
}
def size = 0
}
}
protected def performUpdate(update: String) {
val url = new URL(updateEndpoint)
val con = url.openConnection().asInstanceOf[HttpURLConnection]
//not sure
System.out.println("DEBUG: doing output...")
con.setDoOutput(true)
con.setRequestMethod("POST")
val out = con.getOutputStream()
System.out.println("update: " + update)
out.write(("update=" + URLEncoder.encode(update)).getBytes())
val err = con.getErrorStream()
if (err != null) {
var che = err.read
while (che != -1) {
System.out.write(che)
che = err.read
}
} else {
val in = con.getInputStream()
var ch = in.read
while (ch != -1) {
System.out.write(ch)
ch = in.read
}
}
System.out.flush
}
def getGraph(name: UriRef): Graph = {
throw new NoSuchEntityException(name)
}
def getTriples(name: UriRef): TripleCollection = {
return getMGraph(name)
}
def createMGraph(name: UriRef): MGraph = {
performUpdate("CREATE GRAPH " + name)
val metaGraph = getMGraphNoExistenceCheck(metaGraphName)
metaGraph.add(new TripleImpl(name, RDF.`type`, mGraphClass))
getMGraph(name)
}
def createGraph(name: UriRef, triples: TripleCollection): Graph = {
throw new UnsupportedOperationException
}
def deleteTripleCollection(name: UriRef): Unit = {
throw new UnsupportedOperationException
}
def getNames(graph: Graph): java.util.Set[UriRef] = {
return java.util.Collections.emptySet[UriRef]
}
def listTripleCollections: java.util.Set[UriRef] = {
var result: java.util.Set[UriRef] = new java.util.HashSet[UriRef]
result.addAll(listGraphs)
result.addAll(listMGraphs)
return result
}
def listGraphs: java.util.Set[UriRef] = {
//or should we list graphs for which we have a cached version?
return java.util.Collections.emptySet[UriRef]
}
def listMGraphs: java.util.Set[UriRef] = {
var result: java.util.Set[UriRef] = new java.util.HashSet[UriRef]
result.add(new UriRef("http://fake/sparql"))
result.add(new UriRef(queryEndpoint))
result.add(new UriRef(updateEndpoint))
return result
}
}
object SparqlStorageProvider {
private def tpEncode(res: Resource): String =
res match {
case l: Literal => tpEncode(l)
case u: UriRef => u.toString()
case b: BNode => tpEncode(b)
}
private def tpEncode(lit: Literal): String =
lit match {
case l: PlainLiteral if (l.getLanguage() == null) => "\"\"\"" + l.getLexicalForm() + "\"\"\""
case l: PlainLiteral if (l.getLanguage() != null) => "\"\"\"" + l.getLexicalForm() + "\"\"\"@" + l.getLanguage()
case l: TypedLiteral => "\"\"\"" + l.getLexicalForm() + "\"\"\"^^" + l.getDataType()
}
private def tpEncode(bNode: BNode): String =
//if the bNode has previously been retuned by SPARQL we should add
//TriplePatterns so that the right one is identified
//If this is one that is newly added we must make sure the subsequentyl added
//statements get added, as long as a newly added bNode doesn't add
//new information (would cause a non-lean graph) it is not added to the graph
"_:"
}