--- a/src/main/scala/Authoritative.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/Authoritative.scala Sat Oct 15 23:52:14 2011 -0400
@@ -11,8 +11,10 @@
val uri = req.underlying.getRequestURL.toString
val suffixOpt = uri match {
case r(_, suffix) => Some(suffix)
+ case _ if uri endsWith "/" => Some("/")
case _ => None
}
Some((new URL(uri), Representation(suffixOpt, Accept(req))))
}
+
}
--- a/src/main/scala/Filesystem.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/Filesystem.scala Sat Oct 15 23:52:14 2011 -0400
@@ -7,29 +7,41 @@
import org.slf4j.{Logger, LoggerFactory}
import com.hp.hpl.jena.rdf.model._
import com.hp.hpl.jena.shared.JenaException
-import sys.error
-import scalaz._
+
+import scalaz.{sys => _, _}
import Scalaz._
class Filesystem(
baseDirectory: File,
val basePath: String,
- val lang: String = "RDF/XML-ABBREV")(mode: RWWMode) extends ResourceManager {
+ val lang: Lang)(mode: RWWMode) extends ResourceManager {
val logger: Logger = LoggerFactory.getLogger(this.getClass)
- def sanityCheck(): Boolean = baseDirectory.exists
+ def sanityCheck(): Boolean =
+ baseDirectory.exists && baseDirectory.isDirectory
def resource(url: URL): Resource = new Resource {
val relativePath: String = url.getPath.replaceAll("^"+basePath.toString+"/?", "")
val fileOnDisk = new File(baseDirectory, relativePath)
- private def createFileOnDisk(): Unit = {
- // create parent directory if needed
+ private def parentMustExist(): Unit = {
val parent = fileOnDisk.getParentFile
- if (! parent.exists) println(parent.mkdirs)
+ if (! parent.exists) sys.error("Parent directory %s does not exist" format parent.getAbsolutePath)
+ if (! parent.isDirectory) sys.error("Parent %s is not a directory" format parent.getAbsolutePath)
+ }
+
+ private def createDirectoryOnDisk(): Unit = {
+ parentMustExist()
+ val r = fileOnDisk.mkdir()
+ if (!r) sys.error("Could not create %s" format fileOnDisk.getAbsolutePath)
+ logger.debug("%s successfully created: %s" format (fileOnDisk.getAbsolutePath, r.toString))
+ }
+
+ private def createFileOnDisk(): Unit = {
+ parentMustExist()
val r = fileOnDisk.createNewFile()
- logger.debug("Create file %s with success: %s" format (fileOnDisk.getAbsolutePath, r.toString))
+ logger.debug("%s successfully created: %s" format (fileOnDisk.getAbsolutePath, r.toString))
}
def get(): Validation[Throwable, Model] = {
@@ -37,10 +49,10 @@
if (fileOnDisk.exists()) {
val fis = new FileInputStream(fileOnDisk)
try {
- val reader = model.getReader(lang)
+ val reader = model.getReader(lang.jenaLang)
reader.read(model, fis, url.toString)
} catch {
- case je:JenaException => error("@@@")
+ case je: JenaException => throw je
}
fis.close()
model.success
@@ -56,13 +68,24 @@
try {
createFileOnDisk()
val fos = new FileOutputStream(fileOnDisk)
- val writer = model.getWriter(lang)
+ val writer = model.getWriter(lang.jenaLang)
writer.write(model, fos, url.toString)
fos.close().success
} catch {
case t => t.fail
}
+ def createDirectory(model: Model): Validation[Throwable, Unit] =
+ try {
+ createDirectoryOnDisk().success
+// val fos = new FileOutputStream(fileOnDisk)
+// val writer = model.getWriter(lang.contentType)
+// writer.write(model, fos, url.toString)
+// fos.close().success
+ } catch {
+ case t => t.fail
+ }
+
}
}
--- a/src/main/scala/ReadWriteWebMain.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/ReadWriteWebMain.scala Sat Oct 15 23:52:14 2011 -0400
@@ -27,12 +27,12 @@
}
}
- val rdfLanguage = parser.option[String](List("language"), "l", "RDF language") {
+ val rdfLanguage = parser.option[Lang](List("language"), "l", "RDF language") {
(sValue, opt) =>
sValue match {
- case "n3" => "N3"
- case "turtle" => "N3"
- case "rdfxml" => "RDF/XML-ABBREV"
+ case "n3" => N3
+ case "turtle" => TURTLE
+ case "rdfxml" => RDFXML
case _ => throw new ArgotConversionException("Option %s: must be either n3, turtle or rdfxml" format (opt.name, sValue))
}
}
@@ -64,7 +64,7 @@
new Filesystem(
rootDirectory.value.get,
baseURL.value.get,
- lang=rdfLanguage.value getOrElse "N3")(mode.value getOrElse ResourcesDontExistByDefault)
+ lang=rdfLanguage.value getOrElse RDFXML)(mode.value getOrElse ResourcesDontExistByDefault)
val app = new ReadWriteWeb(filesystem)
--- a/src/main/scala/Representation.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/Representation.scala Sat Oct 15 23:52:14 2011 -0400
@@ -13,14 +13,15 @@
case "turtle" | "ttl" => RDFRepr(TURTLE)
case "rdf" => RDFRepr(RDFXML)
case "htm" | "html" | "xhtml" => HTMLRepr
+ case "/" => DirectoryRepr
case _ => UnknownRepr
}
}
- val htmlCharsets = Set("text/html", "application/xhtml+xml")
+ val htmlContentTypes = Set("text/html", "application/xhtml+xml")
def acceptsHTML(ct: Iterable[String]) =
- ! (htmlCharsets & ct.toSet).isEmpty
+ ! (htmlContentTypes & ct.toSet).isEmpty
def fromAcceptedContentTypes(ct: Iterable[String]): Representation = {
Lang(ct) map RDFRepr.apply getOrElse {
@@ -50,5 +51,5 @@
case class RDFRepr(lang: Lang) extends Representation
case object HTMLRepr extends Representation
+case object DirectoryRepr extends Representation
case object UnknownRepr extends Representation
-case object NoRepr extends Representation
--- a/src/main/scala/Resource.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/Resource.scala Sat Oct 15 23:52:14 2011 -0400
@@ -16,5 +16,6 @@
trait Resource {
def get(): Validation[Throwable, Model]
def save(model: Model): Validation[Throwable, Unit]
+ def createDirectory(model: Model): Validation[Throwable, Unit]
}
--- a/src/main/scala/plan.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/main/scala/plan.scala Sat Oct 15 23:52:14 2011 -0400
@@ -21,15 +21,18 @@
import scalaz._
import Scalaz._
+//object ReadWriteWeb {
+//
+// val defaultHandler: PartialFunction[Throwable, HttpResponse[_]] = {
+// case t => InternalServerError ~> ResponseString(t.getStackTraceString)
+// }
+//
+//}
+
class ReadWriteWeb(rm: ResourceManager) {
val logger: Logger = LoggerFactory.getLogger(this.getClass)
- def isHTML(accepts: List[String]): Boolean = {
- val accept = accepts.headOption
- accept == Some("text/html") || accept == Some("application/xhtml+xml")
- }
-
/** I believe some documentation is needed here, as many different tricks
* are used to make this code easy to read and still type-safe
*
@@ -57,7 +60,7 @@
val Authoritative(uri, representation) = req
val r: Resource = rm.resource(uri)
req match {
- case GET(_) & Accept(accepts) if isHTML(accepts) => {
+ case GET(_) if representation == HTMLRepr => {
val source = Source.fromFile("src/main/resources/skin.html")("UTF-8")
val body = source.getLines.mkString("\n")
Ok ~> ViaSPARQL ~> ContentType("text/html") ~> ResponseString(body)
@@ -75,6 +78,12 @@
case HEAD(_) => Ok ~> ViaSPARQL ~> ContentType(lang.contentType)
}
}
+ case PUT(_) & RequestLang(lang) if representation == DirectoryRepr => {
+ for {
+ bodyModel <- modelFromInputStream(Body.stream(req), uri, lang) failMap { t => BadRequest ~> ResponseString(t.getStackTraceString) }
+ _ <- r.createDirectory(bodyModel) failMap { t => InternalServerError ~> ResponseString(t.getStackTraceString) }
+ } yield Created
+ }
case PUT(_) & RequestLang(lang) =>
for {
bodyModel <- modelFromInputStream(Body.stream(req), uri, lang) failMap { t => BadRequest ~> ResponseString(t.getStackTraceString) }
--- a/src/test/scala/CreateContentSpecs.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/test/scala/CreateContentSpecs.scala Sat Oct 15 23:52:14 2011 -0400
@@ -5,7 +5,7 @@
import dispatch._
-object PutRDFXMLSpec extends FilesystemBased with SomeRDF with SomeURI {
+object PutRDFXMLSpec extends SomePeopleDirectory {
"PUTing an RDF document on Joe's URI (which does not exist yet)" should {
"return a 201" in {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/test/scala/CreateDirectorySpec.scala Sat Oct 15 23:52:14 2011 -0400
@@ -0,0 +1,20 @@
+package org.w3.readwriteweb
+
+import org.w3.readwriteweb.util._
+import org.w3.readwriteweb.utiltest._
+
+import dispatch._
+
+object CreateDirSpec extends FilesystemBased with SomeRDF with SomeURI {
+
+ "PUTing an RDF document on /people/" should {
+ "return a 201" in {
+ val httpCode = Http(dirUri.put(RDFXML, rdfxml) get_statusCode)
+ httpCode must_== 201
+ }
+ "create a directory on disk" in {
+ directory must be directory
+ }
+ }
+
+}
--- a/src/test/scala/ReadWriteWebSpecs.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/test/scala/ReadWriteWebSpecs.scala Sat Oct 15 23:52:14 2011 -0400
@@ -7,6 +7,8 @@
// access content
GetStrictModeSpec, GetWikiModeSpec,
ContentNegociationSpec,
+ // create directory
+ CreateDirSpec,
// create content
PutRDFXMLSpec, PostRDFSpec,
PutInvalidRDFXMLSpec, PostOnNonExistingResourceSpec,
--- a/src/test/scala/util/specs.scala Sat Oct 15 23:51:32 2011 -0400
+++ b/src/test/scala/util/specs.scala Sat Oct 15 23:52:14 2011 -0400
@@ -31,13 +31,13 @@
lazy val mode: RWWMode = ResourcesDontExistByDefault
- lazy val language = "RDF/XML-ABBREV"
+ lazy val lang = RDFXML
- lazy val baseURL = "/2007/wiki"
+ lazy val baseURL = "/wiki"
lazy val root = new File(new File(System.getProperty("java.io.tmpdir")), "readwriteweb")
- lazy val resourceManager = new Filesystem(root, baseURL, language)(mode)
+ lazy val resourceManager = new Filesystem(root, baseURL, lang)(mode)
doBeforeSpec {
if (root.exists) root.deleteRecursively()
@@ -70,15 +70,28 @@
val emptyModel = com.hp.hpl.jena.rdf.model.ModelFactory.createDefaultModel()
- lazy val uri = host / "2007/wiki/people/JoeLambda"
+ lazy val dirUri = host / "wiki/people/"
+
+ lazy val uri = host / "wiki/people/JoeLambda"
lazy val uriBase = baseURI(uri)
+ lazy val directory = new File(root, "people")
+
lazy val resourceOnDisk = new File(root, "people/JoeLambda")
}
-trait SomeDataInStore extends FilesystemBased with SomeRDF with SomeURI {
+trait SomePeopleDirectory extends SomeRDF with SomeURI {
+
+ doBeforeSpec {
+ val httpCode = Http(dirUri.put(RDFXML, rdfxml) get_statusCode)
+ httpCode must_== 201
+ }
+
+}
+
+trait SomeDataInStore extends SomePeopleDirectory {
doBeforeSpec {
val httpCode = Http(uri.put(RDFXML, rdfxml) get_statusCode)