diff --git a/core/pom.xml b/core/pom.xml
index 04cd3a1..794c9f5 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -21,7 +21,7 @@
org.dorestorg.dorest
- 0.0.0-SNAPSHOT
+ 0.0.1-SNAPSHOTorg.dorest.core
diff --git a/core/src/main/scala/org/dorest/server/DoRestApp.scala b/core/src/main/scala/org/dorest/server/DoRestApp.scala
index 95c41d8..6ec2dbb 100644
--- a/core/src/main/scala/org/dorest/server/DoRestApp.scala
+++ b/core/src/main/scala/org/dorest/server/DoRestApp.scala
@@ -17,19 +17,20 @@ package org.dorest.server
import collection.mutable.Buffer
-/** Enables the registration of [[org.dorest.server.HandlerFactory]] objects.
- *
- * This trait is implemented by DoRest servers.
- *
- * @author Michael Eichberg
- */
+/**
+ * Enables the registration of [[org.dorest.server.HandlerFactory]] objects.
+ *
+ * This trait is to be implemented by DoRest servers.
+ *
+ * @author Michael Eichberg
+ */
trait DoRestApp {
- private var _factories: Buffer[HandlerCreator] = Buffer()
+ private var _factories: Buffer[HandlerFactory] = Buffer()
def factories = _factories
- def register(handlerFactory: HandlerCreator) {
+ def register(handlerFactory: HandlerFactory) {
_factories += handlerFactory
}
diff --git a/core/src/main/scala/org/dorest/server/HandlerFactory.scala b/core/src/main/scala/org/dorest/server/HandlerFactory.scala
index 634ab66..896988e 100644
--- a/core/src/main/scala/org/dorest/server/HandlerFactory.scala
+++ b/core/src/main/scala/org/dorest/server/HandlerFactory.scala
@@ -17,229 +17,19 @@ package org.dorest.server
import java.lang.Long
-/** HandlerCreators are responsible for matching URIs and – if the URI matches – to create a new Handler
- * that will then handle the request.
- *
- * '''Thread Safety'''
- * Handler factories have to be thread safe. I.e., handler factories have to support the simultaneous
- * matching of URIs; the DoRest framework use a single Handler factory for matching URIs.
- *
- * @author Michael Eichberg
- */
-trait HandlerCreator {
+/**
+ * HandlerCreators are responsible for matching URIs and – if the URI matches – to create a new Handler
+ * that will then handle the request.
+ *
+ * '''Thread Safety'''
+ * Handler factories have to be thread safe. I.e., handler factories have to support the simultaneous
+ * matching of URIs; the DoRest framework use a single Handler factory for matching URIs.
+ *
+ * @author Michael Eichberg
+ */
+trait HandlerFactory {
def matchURI(path: String, query: String): Option[Handler]
}
-/** @author Michael Eichberg
- */
-abstract class HandlerFactory[T <: Handler] extends HandlerCreator {
-
- protected implicit def namedSegmentToPathSegment(name: String): Named = new Named(name)
-
- /** A function that does nothing.
- */
- // Used to avoid that we have to deal with Option objects or have to deal with null values.
- final def DoNothing(t: T): Unit = {
- /*do nothing*/
- }
-
- // TODO merge path and pathelement; i.e., make pathelement itself a list
- /** The (URI) path of this resource.
- */
- trait PathMatcher {
-
- /** Prepends the given path element to this path and returns a new path object.
- */
- def ::(p: PathElement): PathMatcher
-
- /** Tries to match the path. If the path matches, a list of functions is returned which
- * will then be called; e.g., to complete the initialization of the resource's parameters.
- */
- def matchSegment(path: String): Option[List[(T) ⇒ Unit]]
- }
-
- class ComplexPath(val pe: PathElement, val tail: PathMatcher) extends PathMatcher {
-
- def ::(pe: PathElement): PathMatcher = new ComplexPath(pe, this)
-
- def matchSegment(path: String): Option[List[(T) ⇒ Unit]] = {
- pe.matchSegment(path) match {
- case Some((pathRest, f)) ⇒ {
- // this segment matched, but what about the rest of the path?
- tail.matchSegment(pathRest) map (fs ⇒ f :: fs)
- }
- case _ ⇒ None
- }
- }
- }
-
- object EmptyPath extends PathMatcher {
-
- def ::(p: PathElement): PathMatcher = new ComplexPath(p, this)
-
- def matchSegment(path: String): Option[List[(T) ⇒ Unit]] =
- if (path.size == 0) Some(Nil) else None
- }
-
- trait PathElement {
-
- /** Constructs a new path that consists of the given path element and this element.
- */
- def ::(ps: PathElement): PathMatcher = {
- new ComplexPath(ps, new ComplexPath(this, EmptyPath))
- }
-
- /** Tries to match a maximum length segment of the given path. If the match is successful
- * the rest of the path and a function is returned that – if the whole path can be matched –
- * is called.
- *
- * The primary purpose of the function is to enable the initialization of a resource's variable
- * path parameters.
- */
- def matchSegment(path: String): Option[(String, (T) ⇒ Unit)]
-
- }
-
- /** Can be used to match a path (segment) that is optional and which extends until the end of a given
- * concrete path.
- *
- * If the given path is not empty and does not match the match is considered to have failed
- * unless {link #failOnMatchError} is set to false.
- *
- * Cannot be used to match an optional sub-part of a path. E.g., matching something like
- * {{{"/user"::{"/"userid}::"/tag"}}} where {{{"/"userid"}}} is optional is not possible.
- */
- class Optional(val p: PathMatcher, val failOnMatchError: Boolean) extends PathElement {
-
- def matchSegment(path: String): Option[(String, (T) ⇒ Unit)] = {
- if (path.size == 0) {
- return Some(("", DoNothing))
- }
-
- p.matchSegment(path) match {
- case Some(fs) ⇒ Some(("", (t: T) ⇒ {
- fs.foreach(_(t))
- }))
- case _ ⇒ if (failOnMatchError) None else Some(("", DoNothing))
- }
- }
-
- }
-
- object Optional {
- def apply(pe: PathElement, failOnMatchError: Boolean = true) = {
- new Optional(new ComplexPath(pe, EmptyPath), failOnMatchError)
- }
- }
-
- /** Matches a segment that defines a long value.
- */
- class LongValue(val set: Long ⇒ T ⇒ Unit) extends PathElement {
-
- def matchSegment(path: String): Option[(String, (T) ⇒ Unit)] = {
- LongValue.matcher.findFirstIn(path).map(s ⇒ {
- (path.substring(s.length), set(s.toLong))
- }
- )
- }
- }
-
- object LongValue {
-
- private val matcher = """^-?\d+""".r
-
- def apply(set: Long ⇒ T ⇒ Unit): PathElement = new LongValue(set)
-
- def apply(set: (T, Long) ⇒ Unit): PathElement = apply((v: Long) ⇒ (t: T) ⇒ set(t, v.toLong))
-
- }
-
- /** Matches a string segment that contains a word character or "@".
- */
- class StringValue(set: String ⇒ T ⇒ Unit) extends PathElement {
-
- def matchSegment(path: String): Option[(String, (T) ⇒ Unit)] = {
- StringValue.matcher.findFirstIn(path).map((s) ⇒ {
- (path.substring(s.length), set(s))
- }
- )
- }
- }
-
- object StringValue {
-
- private val matcher = """^(\w|@|-|\.)+""".r
-
- def apply(set: (String) ⇒ (T) ⇒ Unit) = new StringValue(set)
-
- def apply(set: (T, String) ⇒ Unit): PathElement = apply((v: String) ⇒ (t: T) ⇒ set(t, v))
-
- }
-
- class AnyPath(set: String ⇒ T ⇒ Unit) extends PathElement {
- def matchSegment(path: String): Option[(String, T ⇒ Unit)] = {
- Some("" /* The (empty) rest of the path. */ , set(path))
- }
- }
-
- object AnyPath {
- def apply(set: (String) ⇒ (T) ⇒ Unit) = new AnyPath(set)
- }
-
- class Named(val name: String) extends PathElement {
-
- def matchSegment(path: String): Option[(String, (T) ⇒ Unit)] = {
- if (path.startsWith(name)) {
- val pathRest = path.substring(name.length)
- Some((pathRest, DoNothing))
- }
- else {
- None
- }
- }
- }
-
- def matchURI(path: String, query: String): Option[T] = {
- pathMatcher matchSegment (path) map { create(_) }
- /*this.pathMatcher.matchSegment(path) match {
- case Some(fs) ⇒ {
- Some(create(fs))
- }
- case _ ⇒ None
- }*/
- }
-
- private def create(fs: List[(T) ⇒ Unit]): T = {
- val t = create()
- fs.foreach(_(t))
- t
- }
-
- trait QueryMatcher
-
- object NoQuery extends QueryMatcher
-
- private var pathMatcher: PathMatcher = EmptyPath
-
- def path(f: ⇒ PathMatcher) {
- pathMatcher = f
- }
-
- def path(staticPath: String) {
- path {
- staticPath :: EmptyPath
- }
- }
-
- private[this] var queryMatcher: QueryMatcher = NoQuery
-
- def query(f: ⇒ QueryMatcher) {
- queryMatcher = f
- }
-
- /** Creates a new handler object that will be further initialized using the segments extracted by the path matchers.
- */
- def create(): T
-}
diff --git a/core/src/main/scala/org/dorest/server/MappedDirectory.scala b/core/src/main/scala/org/dorest/server/MappedDirectory.scala
index a4ded02..99aa0f5 100644
--- a/core/src/main/scala/org/dorest/server/MappedDirectory.scala
+++ b/core/src/main/scala/org/dorest/server/MappedDirectory.scala
@@ -23,13 +23,11 @@ import java.lang.Boolean
*
* @author Michael Eichberg (mail at michael-eichberg.de)
*/
-class MappedDirectory(val baseDirectory: String, enableIndexHTMLDeliveryOnDirectoryAccess: Boolean = false) extends Handler {
+class MappedDirectory(val baseDirectory: String, val path: String, enableIndexHTMLDeliveryOnDirectoryAccess: Boolean = false) extends Handler {
import java.io._
- var path: String = _
-
- def processRequest(requestBody: => InputStream): Response = {
+ def processRequest(requestBody: ⇒ InputStream): Response = {
if (method != GET) {
return new SupportedMethodsResponse(GET)
}
@@ -53,7 +51,7 @@ class MappedDirectory(val baseDirectory: String, enableIndexHTMLDeliveryOnDirect
val fileName = file.getName
val fileType = {
val fileSuffix = fileName.substring(fileName.lastIndexOf('.') + 1)
- Some((
+ Some((// TODO move to some extensible table
fileSuffix match {
case "css" ⇒ MediaType.TEXT_CSS
case "javascript" ⇒ MediaType.APPLICATION_JAVASCRIPT
@@ -87,20 +85,10 @@ class MappedDirectory(val baseDirectory: String, enableIndexHTMLDeliveryOnDirect
def length = file.length.asInstanceOf[Int]
def write(responseBody: OutputStream) {
- // TODO Read blocks and not just single bytes.
- // TODO Think about caching files.
- /*val in = new FileInputStream(file)
- try {
- while (in.available > 0)
- responseBody.write(in.read)
- } finally {
- if (in != null)
- in.close
- }*/
responseBody.write(readFully(file))
}
- def readFully(file: File) : Array[Byte] = {
+ def readFully(file: File): Array[Byte] = {
val in = new FileInputStream(file)
try {
val length = file.length.asInstanceOf[Int];
diff --git a/core/src/main/scala/org/dorest/server/jdk/Demo.scala b/core/src/main/scala/org/dorest/server/jdk/Demo.scala
index c2e22e4..b26fe93 100644
--- a/core/src/main/scala/org/dorest/server/jdk/Demo.scala
+++ b/core/src/main/scala/org/dorest/server/jdk/Demo.scala
@@ -36,25 +36,25 @@ class Time
}
get returns HTML {
- "
The current (server) time is: "+new java.util.Date().toString+""
+ "The current (server) time is: " + new java.util.Date().toString + ""
}
get returns XML {
}
}
+object Time extends Time with PerformanceMonitor
-class User extends RESTInterface with TEXTSupport {
-
- var user: String = _
+class User(var user: String) extends RESTInterface with TEXTSupport {
get returns TEXT {
- "Welcome "+user
+ "Welcome " + user
}
}
-/** Implementation of a very primitive, thread-safe key-value store.
- */
+/**
+ * Implementation of a very primitive, thread-safe key-value store.
+ */
object KVStore {
private val ds = new scala.collection.mutable.HashMap[Long, String]()
@@ -112,7 +112,7 @@ class Keys extends RESTInterface with XMLSupport {
// convenience method: Location(URI)
// Alternatively, it is possible to directly set the response headers
// using the corresponding response headers data structure.
- Location(new URL("http://"+InetAddress.getLocalHost.getHostName+":9000/keys/"+id.toString)) // TODO enable to specify the relative path
+ Location(new URL("http://" + InetAddress.getLocalHost.getHostName + ":9009/keys/" + id.toString)) // TODO enable to specify the relative path
// the "response body"
{ value }
@@ -120,17 +120,14 @@ class Keys extends RESTInterface with XMLSupport {
}
-class Key extends RESTInterface with XMLSupport {
-
- var id: Long = _
+class Key(val id: Long) extends RESTInterface with XMLSupport {
get returns XML {
KVStore.synchronized {
if (!KVStore.contains(id)) {
responseCode = 404 // 404 = NOT FOUND
None // EMPTY BODY
- }
- else {
+ } else {
val value = KVStore(id)
{ value }
}
@@ -142,8 +139,7 @@ class Key extends RESTInterface with XMLSupport {
if (!KVStore.contains(id)) {
responseCode = 404 // NOT FOUND
None
- }
- else {
+ } else {
KVStore.updated(id, XMLRequestBody.text)
{ XMLRequestBody.text }
}
@@ -156,95 +152,55 @@ class Key extends RESTInterface with XMLSupport {
}
-object Key {
-
- def setId(key: Key, id: Long) {
- key.id = id
- }
-}
-
-class MonitoredMappedDirectory(baseDirectory: String)
- extends MappedDirectory(baseDirectory)
+class MonitoredMappedDirectory(baseDirectory: String, path: String, enableIndexHTMLDeliveryOnDirectoryAccess: Boolean = false)
+ extends MappedDirectory(baseDirectory, path, enableIndexHTMLDeliveryOnDirectoryAccess)
with ConsoleLogging // TODO needs to exchanged
with PerformanceMonitor
class Demo
-/** To test the restful web serice you can use, e.g., curl. For example, to
- * add a value to the simple key-value store you can use:
- *
- * curl -v -X POST -d "Test" -H content-type:application/xml http://localhost:9009/keys
- * curl http://localhost:9009/keys
- */
+/**
+ * To test the restful web serice you can use, e.g., curl. For example, to
+ * add a value to the simple key-value store you can use:
+ *
+ * curl -v -X POST -d "Test" -H content-type:application/xml http://localhost:9009/keys
+ * curl http://localhost:9009/keys
+ */
object Demo
extends JDKServer(9009)
with scala.App
with ConsoleLogging // TODO needs to exchanged
{
- this register new HandlerFactory[Keys] {
- path {
- "/keys"
- }
-
- def create = new Keys
- }
-
- this register new HandlerFactory[Key] {
- path {
- // "/keys/" :: LongValue(v => _.id = v)
-
- //"/keys/" :: LongValue(Key.setId _)
- //"/keys/" :: LongValue((k,l) => k.id = l)
- "/keys/" :: LongValue(_.id = _)
- }
-
- def create = new Key
- }
-
- this register new HandlerFactory[User] {
- path {
- "/user/" :: StringValue(_.user = _)
- }
-
- def create = new User with PerformanceMonitor with ConsoleLogging // TODO needs to exchanged
- }
-
- register(
- new HandlerFactory[Time] {
- path {
- "/time" :: EmptyPath
+ addPathMatcher {
+ / {
+ case "keys" ⇒ / {
+ case MATCHED() ⇒ new Keys
+ case LONG(id) ⇒ new Key(id)
}
- query {
- NoQuery
- }
-
- /** Reusing one instance of a resource to handle all requests requires that the resource is thread safe.
- * If you are unsure, just create a new instance for each request!
- *
- * If your resource is not trivially thread-safe, we recommend that you do not try to make it thread safe
- * and instead just create a new instance. (i.e., you don't write "lazy val" but write "def" in following.)
- *
- * In general, whenever you have to extract path parameters or have to process a request body or your
- * object representing the resource has some kind of mutable state, it is relatively certain that you
- * have to create a new instance to handle a request.
- */
- lazy val create = new Time() with PerformanceMonitor
- })
-
- // ("timezone",StringValue(v => _.timeZone = v))
-
- register(
- new HandlerFactory[MappedDirectory] {
- path {
- "/static" :: AnyPath(
- v ⇒ _.path = {
- if (v startsWith "/") v else "/"+v
- })
+ case "user" ⇒ / {
+ case STRING(userId) ⇒ new User(userId) with PerformanceMonitor with ConsoleLogging
}
-
- def create = new MonitoredMappedDirectory(System.getProperty("user.home"))
- })
+ case "time" ⇒
+ /**
+ * Reusing one instance of a resource to handle all requests requires that the resource is thread safe.
+ * If you are unsure, just create a new instance for each request!
+ *
+ * If your resource is not trivially thread-safe, we recommend that you do not try to make it thread safe
+ * and instead just create a new instance.
+ *
+ * In general, whenever you have to extract path parameters or have to process a request body or your
+ * object representing the resource has some kind of mutable state, it is relatively certain that you
+ * have to create a new instance to handle a request.
+ */
+ Time
+ case "static" ⇒ (path) ⇒
+ if (path eq null)
+ None
+ else
+ Some(new MonitoredMappedDirectory(System.getProperty("user.home"), path))
+ }
+ }
// start the server
start()
diff --git a/core/src/main/scala/org/dorest/server/jdk/JDKServer.scala b/core/src/main/scala/org/dorest/server/jdk/JDKServer.scala
index 5dba637..52f7ba7 100644
--- a/core/src/main/scala/org/dorest/server/jdk/JDKServer.scala
+++ b/core/src/main/scala/org/dorest/server/jdk/JDKServer.scala
@@ -16,9 +16,11 @@
package org.dorest.server
package jdk
+import log._
+import rest._
+
import com.sun.net.httpserver._
import java.net._
-import log._
import java.util.concurrent.Executor
import java.util.concurrent.Executors
@@ -39,6 +41,7 @@ import java.util.concurrent.Executors
class JDKServer(val port : Int,val executor : Executor = Executors.newCachedThreadPool())
extends DoRestServer
with DoRestApp
+ with URIsMatcher
{
private[this] val logger = Logger(classOf[JDKServer])
diff --git a/core/src/main/scala/org/dorest/server/rest/URIsMatcher.scala b/core/src/main/scala/org/dorest/server/rest/URIsMatcher.scala
index bc69454..4e71254 100644
--- a/core/src/main/scala/org/dorest/server/rest/URIsMatcher.scala
+++ b/core/src/main/scala/org/dorest/server/rest/URIsMatcher.scala
@@ -21,10 +21,20 @@ package rest
*
* @author Michael Eichberg
*/
-trait RESTURIsMatcher {
+trait URIsMatcher {
+
+ type PathMatcher = (String) ⇒ Option[Handler]
// NEEDS TO BE PROVIDED BY THE CLASS WHERE THIS CLASS IS MIXED IN
- // def register(handlerFactory: HandlerFactory[Handler])
+ def register(handlerFactory: HandlerFactory): Unit
+
+ def addPathMatcher(pathMatcher: PathMatcher) {
+ register(new HandlerFactory {
+ def matchURI(path: String, query: String): Option[Handler] = {
+ pathMatcher(path)
+ }
+ })
+ }
/**
* Use ROOT to match a URI that ends with "/" and where all previous segments have been successfully
@@ -71,13 +81,11 @@ trait RESTURIsMatcher {
}
}
- type PathMatcher = (String) ⇒ Option[Handler]
-
case class /(matcher: PartialFunction[String, PathMatcher]) extends PathMatcher {
/**
* @param completePath A valid URI path (or the yet unmatched part of the URI).
- * The completePath is either null or is a string that starts with a "/".
+ * The completePath is either null or is a string that starts with a "/".
* The semantics of null is that the complete path was matched; i.e., there
* is no remaining part.
*/
@@ -112,24 +120,6 @@ trait RESTURIsMatcher {
/(matcher)
}
- // def addPath(pathMatcher: PathMatcher) {
- //
- // }
-
- // this addPath (
- // / {
- // case ROOT() ⇒ new Handler {}
- // case "lectures" ⇒ / {
- // case EOL() ⇒ new Handler {} /* General information about lectures */
- // case ROOT() ⇒ new Handler {} /* The lectures */
- // case STRING(lectureId) ⇒ / {
- // //case NIL ⇒ null /* General Information about the lecture */
- // case "slides" ⇒ new Handler {}
- // }
- // }
- // case "users" ⇒ new Handler {}
- // }
- // )
}
diff --git a/core/src/test/scala/org/dorest/server/rest/URIsMatcherTest.scala b/core/src/test/scala/org/dorest/server/rest/URIsMatcherTest.scala
index 6d1504b..aece6a5 100644
--- a/core/src/test/scala/org/dorest/server/rest/URIsMatcherTest.scala
+++ b/core/src/test/scala/org/dorest/server/rest/URIsMatcherTest.scala
@@ -22,10 +22,12 @@ import org.scalatest.FlatSpec
import org.scalatest.matchers.ShouldMatchers
/**
+ * Tests the matching of URIs.
+ *
* @author Michael Eichberg
*/
@RunWith(classOf[JUnitRunner])
-class RESTURIsMatcherTest extends FlatSpec with ShouldMatchers {
+class URIsMatcherTest extends FlatSpec with ShouldMatchers {
// just some dummy handlers
class DummyHandler extends Handler {
@@ -42,35 +44,43 @@ class RESTURIsMatcherTest extends FlatSpec with ShouldMatchers {
object GHandler extends DummyHandler
case class LongHandler(l: Long) extends DummyHandler
+ case class PathHandler(p: String) extends DummyHandler
// some URIMatcher instance
- val URIMatcher = new RESTURIsMatcher {}
+ val URIMatcher = new URIsMatcher {
+
+ def register(handlerFactory: HandlerFactory) { throw new Error() }
+
+ }
import URIMatcher._
- val exhaustiveMatcher = / {
+ val exhaustiveMatcher = / {
case "" ⇒ AHandler
case "lectures" ⇒ BHandler
case "users" ⇒ / {
- case MATCHED() ⇒ CHandler
- case ROOT() ⇒ DHandler
+ case MATCHED() ⇒ CHandler
+ case ROOT() ⇒ DHandler
case LONG(userId) if userId > 0 ⇒ / {
case EOL() ⇒ LongHandler(userId)
case ROOT() ⇒ FHandler
case "comments" ⇒ GHandler
}
-
}
+ case "static" ⇒ (path: String) ⇒ Some(PathHandler(path))
}
"A RESTURIsMatcher" should "correctly match valid URIs" in {
- exhaustiveMatcher("/") should be (Some(AHandler))
+ exhaustiveMatcher("/") should be(Some(AHandler))
exhaustiveMatcher("/lectures") should be(Some(BHandler))
exhaustiveMatcher("/users") should be(Some(CHandler))
exhaustiveMatcher("/users/") should be(Some(DHandler))
exhaustiveMatcher("/users/121212") should be(Some(LongHandler(121212)))
exhaustiveMatcher("/users/23233321212/") should be(Some(FHandler))
exhaustiveMatcher("/users/23233321212/comments") should be(Some(GHandler))
+ exhaustiveMatcher("/static") should be(Some(PathHandler(null)))
+ exhaustiveMatcher("/static/") should be(Some(PathHandler("/")))
+ exhaustiveMatcher("/static/index.html") should be(Some(PathHandler("/index.html")))
}
it should "handle URIs that do not match without throwing exceptions" in {
diff --git a/demo/HelloWorld/pom.xml b/demo/HelloWorld/pom.xml
index 620d90d..2e1f8e3 100644
--- a/demo/HelloWorld/pom.xml
+++ b/demo/HelloWorld/pom.xml
@@ -20,7 +20,7 @@
4.0.0de.somegrouphelloworld
- 0.0.1-SNAPSHOT
+ 1.0.0${project.artifactId}
@@ -56,7 +56,7 @@
org.dorestorg.dorest.core
- 0.0.0-SNAPSHOT
+ 0.0.1-SNAPSHOT
@@ -69,7 +69,7 @@
junitjunit
- 4.8.2
+ 4.10test
diff --git a/demo/HelloWorld/src/main/scala/helloworld/HelloWorldServer.scala b/demo/HelloWorld/src/main/scala/helloworld/HelloWorldServer.scala
index 10f60e9..5c9ffd0 100644
--- a/demo/HelloWorld/src/main/scala/helloworld/HelloWorldServer.scala
+++ b/demo/HelloWorld/src/main/scala/helloworld/HelloWorldServer.scala
@@ -18,22 +18,16 @@ package helloworld
import org.dorest.server.jdk.JDKServer
import org.dorest.server.rest.RESTInterface
import org.dorest.server.rest.TEXTSupport
-import org.dorest.server.HandlerFactory
-// server object
-object HelloWorldServer extends JDKServer(9000) with App {
+object HelloWorldServer extends JDKServer(9010) with App {
- // registering the handler
- this register new HandlerFactory[HelloWorldHandler] {
- path { "/hello" }
- def create = new HelloWorldHandler
- }
-
- // handler
- class HelloWorldHandler extends RESTInterface with TEXTSupport {
- get returns TEXT { "Hello World!" }
- }
-
- start()
+ this addPathMatcher {
+ / {
+ case "hello" ⇒ new RESTInterface with TEXTSupport {
+ get returns TEXT { "Hello World!" }
+ }
+ }
+ }
+ start()
}
diff --git a/demo/iSmallNotes/pom.xml b/demo/iSmallNotes/pom.xml
index e2d24d2..958246c 100644
--- a/demo/iSmallNotes/pom.xml
+++ b/demo/iSmallNotes/pom.xml
@@ -21,13 +21,13 @@
org.dorestorg.dorest.demos
- 0.0.0-SNAPSHOT
+ 0.0.1-SNAPSHOTde.smallnotesde.smallnotesiSmallNotes
-
+
@@ -40,7 +40,7 @@
-
+
org.dorest
diff --git a/demo/iSmallNotes/src/main/scala/de/smallnotes/Notes.scala b/demo/iSmallNotes/src/main/scala/de/smallnotes/Notes.scala
index c727f77..f2d71f9 100644
--- a/demo/iSmallNotes/src/main/scala/de/smallnotes/Notes.scala
+++ b/demo/iSmallNotes/src/main/scala/de/smallnotes/Notes.scala
@@ -2,16 +2,14 @@ package de.smallnotes
import org.dorest.server.rest.RESTInterface
import org.dorest.server.rest.representation.orgjson.ORGJSONSupport
-import org.json.{JSONObject, JSONArray}
+import org.json.{ JSONObject, JSONArray }
-class Notes
+class Notes(var tagId: Long)
extends RESTInterface
with SmallNotesAuthorization
with JDBCTransactionProvider
with ORGJSONSupport {
- var t_id: Long = _
-
get returns JSON {
val stmt = connection.prepareStatement(
"""
@@ -21,7 +19,7 @@ class Notes
"""
)
stmt.setString(1, authenticatedUser)
- stmt.setLong(2, t_id)
+ stmt.setLong(2, tagId)
val rs = stmt.executeQuery()
val ja = new JSONArray()
while (rs.next()) {
@@ -38,7 +36,7 @@ class Notes
val call = connection.prepareCall("{call add_note(?,?,?,?)}")
call.registerOutParameter(4, java.sql.Types.BIGINT)
call.setString(1, authenticatedUser)
- call.setLong(2, t_id)
+ call.setLong(2, tagId)
call.setString(3, note)
call.execute()
val jo = new JSONObject()
diff --git a/demo/iSmallNotes/src/main/scala/de/smallnotes/SmallNotesApplication.scala b/demo/iSmallNotes/src/main/scala/de/smallnotes/SmallNotesApplication.scala
index db75abf..c1cbf85 100644
--- a/demo/iSmallNotes/src/main/scala/de/smallnotes/SmallNotesApplication.scala
+++ b/demo/iSmallNotes/src/main/scala/de/smallnotes/SmallNotesApplication.scala
@@ -1,53 +1,38 @@
package de.smallnotes
-import org.dorest.server.{MappedDirectory, HandlerFactory}
+import org.dorest.server.{ MappedDirectory, HandlerFactory }
import org.dorest.server.jdk.JDKServer
class SmallNotesApplication
object SmallNotesApplication extends JDKServer(8182) with App {
- this register new HandlerFactory[Notes] {
- path {
- "/api/tags/" :: LongValue((v) => _.t_id = v) :: "/notes" :: Optional("/")
- }
-
- def create = new Notes
- }
-
- this register new HandlerFactory[Tag] {
- path {
- "/tags/" :: LongValue((v) => _.id = v)
- }
-
- def create = new Tag
- }
-
- this register new HandlerFactory[Tags] {
- path {
- "/api/tags"
- }
-
- def create(): Tags = new Tags
+ val rootWebappFolder = {
+ var rwf = System.getProperty("de.smallnotes.resources.webapp")
+ if (!(rwf eq null))
+ rwf
+ else
+ "src/main/resources/webapp"
}
- this register new HandlerFactory[MappedDirectory] {
- path {
- "/webapp" :: AnyPath((v) => _.path = v)
+ this addPathMatcher (
+ / {
+ case "api" ⇒ / {
+ case "tags" ⇒ / {
+ case MATCHED() ⇒ new Tags
+ case LONG(tagId) ⇒ / {
+ case "notes" ⇒ new Notes(tagId)
+ }
+ }
+ }
+ case "tags" ⇒ / {
+ case LONG(id) ⇒ new Tag(id)
+ }
+ case "webapp" ⇒ (path) ⇒ Some(new MappedDirectory(rootWebappFolder, path, true))
}
-
- def create(): MappedDirectory = new MappedDirectory({
-
- val dir = System.getProperty("de.smallnotes.resources.webapp")
- if (!(dir eq null))
- dir
- else
- "src/main/resources/webapp"
- },true)
- }
+ )
start()
-
}
diff --git a/demo/iSmallNotes/src/main/scala/de/smallnotes/Tag.scala b/demo/iSmallNotes/src/main/scala/de/smallnotes/Tag.scala
index 149276c..0d59938 100644
--- a/demo/iSmallNotes/src/main/scala/de/smallnotes/Tag.scala
+++ b/demo/iSmallNotes/src/main/scala/de/smallnotes/Tag.scala
@@ -3,14 +3,12 @@ package de.smallnotes
import org.dorest.server.rest.RESTInterface
import org.dorest.server.rest.representation.orgjson.ORGJSONSupport
-class Tag
+class Tag(val id: Long)
extends RESTInterface
with SmallNotesAuthorization
with JDBCTransactionProvider
with ORGJSONSupport {
- var id: Long = _
-
delete {
// TODO model as function... delete_user_tag
val stmt = connection.prepareStatement("delete from \"TAGS\" where id=?")
diff --git a/demo/pom.xml b/demo/pom.xml
index acad7cc..609e847 100644
--- a/demo/pom.xml
+++ b/demo/pom.xml
@@ -1,13 +1,13 @@
+
4.0.0
@@ -21,7 +11,7 @@
org.dorestorg.dorest
- 0.0.0-SNAPSHOT
+ 0.0.1-SNAPSHOTorg.dorest.ext
@@ -35,7 +25,6 @@
orgjsongsonservlet
- tiscafclientstreammultipart
@@ -78,11 +67,6 @@
org.dorest.ext.servlet${project.version}
-
- org.dorest
- org.dorest.ext.tiscaf
- ${project.version}
- org.dorestorg.dorest.ext.client
diff --git a/ext/servlet/pom.xml b/ext/servlet/pom.xml
index fa26f01..d78d6c8 100644
--- a/ext/servlet/pom.xml
+++ b/ext/servlet/pom.xml
@@ -1,13 +1,13 @@