blob: e1b4630150733db6f3448f492d1baae5e7ffd7c3 [file] [log] [blame]
package org.apache.clerezza.platform.graphnodeprovider
/*
* 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.
*/
import java.net.{HttpURLConnection, URL}
import org.slf4j.scala._
import org.apache.clerezza.rdf.core.access._
import org.apache.clerezza.rdf.core._
import org.apache.clerezza.platform.config.PlatformConfig
import org.apache.clerezza.platform.Constants
import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider
import org.apache.clerezza.platform.users.WebIdGraphsService
import org.apache.clerezza.rdf.utils.{UnionMGraph, UriMutatingTripleCollection, GraphNode}
import java.util.concurrent.locks.Lock
import org.apache.clerezza.platform.usermanager.UserManager
import java.security.{PrivilegedAction, AccessController}
import org.apache.clerezza.rdf.utils.graphnodeprovider.GraphNodeProvider
/**
* A service that returns a GraphNode for a specified named resource, the returned GraphNode has
* as BaseGraph the ContentGraph provided by the ContentGraphProvider and the for remote uris the
* Graphs they dereference to and for local URIs with a path-section starting with /user/{username}/
* the local-public-graph of that user.
*/
class PlatformGraphNodeProvider extends GraphNodeProvider with Logging {
/**
* Get a GraphNode for the specified resource, see class comments for details.
*/
def get(uriRef: UriRef): GraphNode = {
val uriString = uriRef.getUnicodeString
val isLocal: Boolean = {
import scala.collection.JavaConversions._
//we assume all non http* uris to be local
!uriString.toLowerCase.startsWith("http") || platformConfig.getBaseUris.exists(baseUri => uriString.startsWith(baseUri.getUnicodeString))
}
get(uriRef, isLocal)
}
/**
* Get a GraphNode for the specified resource, The resource is assumed to be local, i.e. the method behaves like
* get(UriRef) for a Uri with an authority section contained in the Set retuned by
* <code>org.apache.clerezza.platform.config.PlatformConfig#getBaseUris()</code>
*/
def getLocal(uriRef: UriRef): GraphNode = {
get(uriRef, true)
}
/**
*return true iff getLocal(uriRef).getNodeContext.size > 0
*/
def existsLocal(uriRef: UriRef): Boolean = {
val cgGraph = cgProvider.getContentGraph
lazy val localInstanceUri = {
val uri = new java.net.URI(uriRef.getUnicodeString)
new UriRef(Constants.URN_LOCAL_INSTANCE + uri.getPath)
}
//TODO handle /user/
existsInGraph(uriRef,cgGraph) || existsInGraph(localInstanceUri, cgGraph)
}
private[this] def existsInGraph(nodeUri: UriRef, tc: LockableMGraph): Boolean = {
var readLock: Lock = tc.getLock.readLock
readLock.lock
try {
return tc.filter(nodeUri, null, null).hasNext || tc.filter(null, null, nodeUri).hasNext
}
finally {
readLock.unlock
}
}
private def get(uriRef: UriRef, isLocal: Boolean): GraphNode = {
val uriString = uriRef.getUnicodeString
val uriPath = {
val uri = new java.net.URI(uriString)
uri.getPath
}
lazy val uriPrefix = {
val uri = new java.net.URI(uriString)
uri.getScheme+"://"+uri.getAuthority
}
val anyHostUri = new UriRef(Constants.URN_LOCAL_INSTANCE + uriPath)
var mGraphs: List[TripleCollection] = Nil
def addToUnion(mGraph: LockableMGraph) {
//adding uncondinionately if (existsInGraph(uriRef, mGraph)) {
mGraphs ::= mGraph
//}
if (isLocal) {
if (existsInGraph(anyHostUri, mGraph)) {
mGraphs ::= new UriMutatingTripleCollection(mGraph, Constants.URN_LOCAL_INSTANCE, uriPrefix)
}
}
}
val cgGraph = cgProvider.getContentGraph
addToUnion(cgGraph)
if (isLocal && (uriPath != null) && uriPath.startsWith("/user/")) {
val nextSlash = uriPath.indexOf('/',6)
if (nextSlash != -1) {
val userName = uriPath.substring(6, nextSlash)
val webIdOption = AccessController.doPrivileged(new PrivilegedAction[Option[UriRef]]() {
def run(): Option[UriRef] = {
val userNode: GraphNode = userManager.getUserInSystemGraph(userName)
if (userNode != null) {
userNode.getNode match {
case u: UriRef => Some(u)
case _ => None
}
} else {
None
}
}
}
)
webIdOption match {
case Some(u) => {
val webIdInfo = webIdGraphsService.getWebIdInfo(u)
addToUnion(webIdInfo.localPublicUserData)
}
case None => ;
}
}
}
if (!isLocal) {
/**
* As the resource might identify something other than a document we use this to find the redirect location
*/
lazy val redirectLocationString = {
val acceptHeader = "application/rdf+xml,*/*;q.1"
val url = new URL(uriString)
val connection = url.openConnection()
connection match {
case hc : HttpURLConnection => {
hc.setRequestMethod("HEAD");
hc.setInstanceFollowRedirects(false)
hc.addRequestProperty("Accept", acceptHeader)
hc.getResponseCode match {
case HttpURLConnection.HTTP_SEE_OTHER => {
val location = hc.getHeaderField("Location")
if (location == null) {
throw new RuntimeException("No Location Headers in 303 response")
}
location
}
case _ => uriString
}
}
case _ => uriString
}
}
//TODO add method to WebProxy to get the graph location location
val graphUriString = {
val hashPos = uriString.indexOf('#')
if (hashPos != -1) {
uriString.substring(0, hashPos)
} else {
redirectLocationString
}
}
addToUnion(tcManager.getMGraph(new UriRef(graphUriString)))
}
val unionMGraph = new UnionMGraph(mGraphs:_*);
new GraphNode(uriRef, unionMGraph)
}
private var tcManager: TcManager = null;
protected def bindTcManager(tcManager: TcManager) = {
this.tcManager = tcManager
}
protected def unbindTcManager(tcManager: TcManager) = {
this.tcManager = null
}
private var platformConfig: PlatformConfig = null;
protected def bindPlatformConfig(c: PlatformConfig) = {
this.platformConfig = c
}
protected def unbindPlatformConfig(c: PlatformConfig) = {
this.platformConfig = null
}
private var cgProvider: ContentGraphProvider = null
protected def bindCgProvider(p: ContentGraphProvider) {
this.cgProvider = p
}
protected def unbindCgProvider(p: ContentGraphProvider) {
this.cgProvider = null
}
private var webIdGraphsService: WebIdGraphsService = null
protected def bindWebIdGraphsService(webIdGraphsService: WebIdGraphsService): Unit = {
this.webIdGraphsService = webIdGraphsService
}
protected def unbindWebIdGraphsService(webIdGraphsService: WebIdGraphsService): Unit = {
this.webIdGraphsService = null
}
private var userManager: UserManager = null
protected def bindUserManager(userManager: UserManager): Unit = {
this.userManager = userManager
}
protected def unbindUserManager(userManager: UserManager): Unit = {
this.userManager = null
}
}