| author | Fabian Huch <huch@in.tum.de> | 
| Wed, 05 Jun 2024 20:09:04 +0200 | |
| changeset 80257 | 96cb31f0bbdf | 
| parent 80256 | df8fa0393127 | 
| child 80315 | a82db14570cd | 
| permissions | -rw-r--r-- | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
1  | 
/* Title: Pure/System/web_app.scala  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
2  | 
Author: Fabian Huch, TU Muenchen  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
3  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
4  | 
Technical layer for web apps using server-side rendering with HTML forms.  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
5  | 
*/  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
6  | 
package isabelle  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
7  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
8  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
9  | 
import scala.annotation.tailrec  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
10  | 
import scala.collection.immutable.SortedMap  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
11  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
12  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
13  | 
object Web_App {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
14  | 
/* form html elements */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
15  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
16  | 
  object More_HTML {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
17  | 
import HTML._  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
18  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
19  | 
    def css(s: String): Attribute = new Attribute("style", s)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
20  | 
    def name(n: String): Attribute = new Attribute("name", n)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
21  | 
    def value(v: String): Attribute = new Attribute("value", v)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
22  | 
    def placeholder(p: String): Attribute = new Attribute("placeholder", p)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
23  | 
|
| 80257 | 24  | 
    val nav = new Operator("nav")
 | 
25  | 
    val header = new Operator("header")
 | 
|
26  | 
    val footer = new Operator("footer")
 | 
|
27  | 
    val main = new Operator("main")
 | 
|
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
28  | 
    val fieldset = new Operator("fieldset")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
29  | 
    val button = new Operator("button")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
30  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
31  | 
    def legend(txt: String): XML.Elem = XML.Elem(Markup("legend", Nil), text(txt))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
32  | 
    def input(typ: String): XML.Elem = XML.Elem(Markup("input", List("type" -> typ)), Nil)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
33  | 
def hidden(k: Params.Key, v: String): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
34  | 
      id(k.print)(name(k.print)(value(v)(input("hidden"))))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
35  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
36  | 
def textfield(i: Params.Key, p: String, v: String): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
37  | 
      id(i.print)(name(i.print)(value(v)(placeholder(p)(input("text")))))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
38  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
39  | 
def browse(i: Params.Key, accept: List[String]): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
40  | 
      id(i.print)(name(i.print)(input("file"))) + ("accept" -> accept.mkString(","))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
41  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
42  | 
def label(`for`: Params.Key, txt: String): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
43  | 
      XML.Elem(Markup("label", List("for" -> `for`.print)), text(txt))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
44  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
45  | 
    def option(k: String, v: String): XML.Elem = value(k)(XML.elem("option", text(v)))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
46  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
47  | 
def optgroup(txt: String, opts: XML.Body): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
48  | 
      XML.Elem(Markup("optgroup", List("label" -> txt)), opts)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
49  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
50  | 
def select(i: Params.Key, opts: XML.Body): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
51  | 
      id(i.print)(name(i.print)(XML.elem("select", opts)))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
52  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
53  | 
def textarea(i: Params.Key, v: String): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
54  | 
      id(i.print)(name(i.print)(value(v)(XML.elem("textarea", text(v + "\n")))))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
55  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
56  | 
    def radio(i: Params.Key, v: Params.Key, values: List[(Params.Key, String)]): XML.Elem = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
57  | 
      def to_option(k: Params.Key): XML.Elem = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
58  | 
        val elem = id(i.print + k)(name(i.print)(value(k.print)(input("radio"))))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
59  | 
        if (v == k) elem + ("checked" -> "checked") else elem
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
60  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
61  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
62  | 
      span(values.map { case (k, v) => span(List(label(i + k, v), to_option(k))) })
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
63  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
64  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
65  | 
    def selection(i: Params.Key, selected: Option[String], opts: XML.Body): XML.Elem = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
66  | 
      def sel(elem: XML.Tree): XML.Tree = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
67  | 
        selected match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
68  | 
case Some(value) =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
69  | 
            val Value = new Properties.String("value")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
70  | 
            elem match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
71  | 
              case XML.Elem(Markup("optgroup", props), body) =>
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
72  | 
                XML.Elem(Markup("optgroup", props), body.map(sel))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
73  | 
              case e@XML.Elem(Markup("option", Value(v)), _) if v == value =>
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
74  | 
                e + ("selected" -> "selected")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
75  | 
case e => e  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
76  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
77  | 
case None => elem  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
78  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
79  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
80  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
81  | 
      def is_empty_group(elem: XML.Tree): Boolean = elem match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
82  | 
        case XML.Elem(Markup("optgroup", _), body) if body.isEmpty => true
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
83  | 
case _ => false  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
84  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
85  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
86  | 
      val default = if (selected.isEmpty) List(option("", "") + ("hidden" -> "hidden")) else Nil
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
87  | 
select(i, default ::: opts.filterNot(is_empty_group).map(sel))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
88  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
89  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
90  | 
def api_button(call: String, label: String): XML.Elem =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
91  | 
      button(text(label)) + ("formaction" -> call) + ("type" -> "submit")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
92  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
93  | 
    def submit_form(endpoint: String, body: XML.Body): XML.Elem = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
94  | 
      val default_button = css("display: none")(input("submit") + ("formaction" -> endpoint))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
95  | 
val attrs =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
96  | 
        List("method" -> "post", "target" -> "iframe", "enctype" -> "multipart/form-data")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
97  | 
      XML.Elem(Markup("form", attrs), default_button :: body)
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
98  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
99  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
100  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
101  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
102  | 
/* form http handling */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
103  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
104  | 
  object Multi_Part {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
105  | 
abstract class Data(name: String)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
106  | 
case class Param(name: String, value: String) extends Data(name)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
107  | 
case class File(name: String, file_name: String, content: Bytes) extends Data(name)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
108  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
109  | 
    def parse(body: Bytes): List[Data] = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
110  | 
/* Seq for text with embedded bytes */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
111  | 
      case class Seq(text: String, bytes: Bytes) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
112  | 
        def split_one(sep: String): Option[(Seq, Seq)] = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
113  | 
val text_i = text.indexOf(sep)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
114  | 
          if (text_i >= 0 && sep.nonEmpty) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
115  | 
val (before_text, at_text) = text.splitAt(text_i)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
116  | 
val after_text = at_text.substring(sep.length)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
117  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
118  | 
// text might be shorter than bytes because of misinterpreted characters  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
119  | 
var found = false  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
120  | 
var bytes_i = 0  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
121  | 
            while (!found && bytes_i < bytes.length) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
122  | 
var sep_ok = true  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
123  | 
var sep_i = 0  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
124  | 
              while (sep_ok && sep_i < sep.length) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
125  | 
                if (bytes.charAt(bytes_i + sep_i) == sep.charAt(sep_i)) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
126  | 
sep_i += 1  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
127  | 
                } else {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
128  | 
bytes_i += 1  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
129  | 
sep_ok = false  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
130  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
131  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
132  | 
if (sep_ok) found = true  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
133  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
134  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
135  | 
val before_bytes = bytes.subSequence(0, bytes_i)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
136  | 
val after_bytes = bytes.subSequence(bytes_i + sep.length, bytes.length)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
137  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
138  | 
Some(Seq(before_text, before_bytes), Seq(after_text, after_bytes))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
139  | 
} else None  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
140  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
141  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
142  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
143  | 
val s = Seq(body.text, body)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
144  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
145  | 
def perhaps_unprefix(pfx: String, s: Seq): Seq =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
146  | 
        Library.try_unprefix(pfx, s.text) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
147  | 
case Some(text) => Seq(text, s.bytes.subSequence(pfx.length, s.bytes.length))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
148  | 
case None => s  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
149  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
150  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
151  | 
val Separator = """--(.*)""".r  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
152  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
153  | 
      s.split_one(HTTP.NEWLINE) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
154  | 
case Some(Seq(Separator(sep), _), rest) =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
155  | 
val Param = """Content-Disposition: form-data; name="([^"]+)"""".r  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
156  | 
val File = """Content-Disposition: form-data; name="([^"]+)"; filename="([^"]+)"""".r  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
157  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
158  | 
def parts(body: Seq): Option[List[Data]] =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
159  | 
            for {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
160  | 
(first_line, more) <- body.split_one(HTTP.NEWLINE)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
161  | 
more1 = perhaps_unprefix(HTTP.NEWLINE, more)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
162  | 
(value, rest) <- more1.split_one(HTTP.NEWLINE + "--" + sep)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
163  | 
rest1 = perhaps_unprefix(HTTP.NEWLINE, rest)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
164  | 
            } yield first_line.text match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
165  | 
case Param(name) =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
166  | 
Multi_Part.Param(name, Line.normalize(value.text)) :: parts(rest1).getOrElse(Nil)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
167  | 
case File(name, file_name) =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
168  | 
                value.split_one(HTTP.NEWLINE + HTTP.NEWLINE) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
169  | 
case Some(_, content) =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
170  | 
Multi_Part.File(name, file_name, content.bytes) :: parts(rest1).getOrElse(Nil)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
171  | 
case _ => parts(rest1).getOrElse(Nil)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
172  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
173  | 
case _ => Nil  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
174  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
175  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
176  | 
parts(rest).getOrElse(Nil)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
177  | 
case _ => Nil  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
178  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
179  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
180  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
181  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
182  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
183  | 
/* request parameters as structured data */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
184  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
185  | 
  object Params {
 | 
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
186  | 
def key(s: String): Key = Key(List(Key.elem(s)))  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
187  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
188  | 
    object Key {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
189  | 
      sealed trait Elem { def print: String }
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
190  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
191  | 
      class Nested_Elem private[Key](val rep: String) extends Elem {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
192  | 
override def equals(that: Any): Boolean =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
193  | 
          that match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
194  | 
case other: Nested_Elem => rep == other.rep  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
195  | 
case _ => false  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
196  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
197  | 
override def hashCode(): Int = rep.hashCode  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
198  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
199  | 
def print: String = rep  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
200  | 
override def toString: String = print  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
201  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
202  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
203  | 
      class List_Elem private[Key](val rep: Int) extends Elem {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
204  | 
override def equals(that: Any): Boolean =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
205  | 
          that match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
206  | 
case other: List_Elem => rep == other.rep  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
207  | 
case _ => false  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
208  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
209  | 
override def hashCode(): Int = rep.hashCode  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
210  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
211  | 
def print: String = rep.toString  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
212  | 
override def toString: String = print  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
213  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
214  | 
|
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
215  | 
def elem(s: String): Elem =  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
216  | 
        if (s.contains('/')) error("Illegal separator in " + quote(s))
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
217  | 
        else {
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
218  | 
          for {
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
219  | 
c <- s  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
220  | 
if Symbol.is_ascii_blank(c)  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
221  | 
          } error("Illegal blank character " + c.toInt + " in " + quote(s))
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
222  | 
          s match {
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
223  | 
case Value.Int(i) => new List_Elem(i)  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
224  | 
case s => new Nested_Elem(s)  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
225  | 
}  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
226  | 
}  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
227  | 
|
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
228  | 
      def elem(i: Int): List_Elem = if (i < 0) error("Illegal list element") else new List_Elem(i)
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
229  | 
|
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
230  | 
def is_blank(es: List[Elem]): Boolean = es.length <= 1 && es.forall(_.print.isBlank)  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
231  | 
      def apply(es: List[Elem]): Key = if (is_blank(es)) error("Empty key") else new Key(es)
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
232  | 
|
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
233  | 
      def explode(s: String): Key = Key(space_explode('/', s).map(elem))
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
234  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
235  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
236  | 
/* ordering */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
237  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
238  | 
      object Ordering extends scala.math.Ordering[Key] {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
239  | 
def compare(key1: Key, key2: Key): Int = key1.print.compareTo(key2.print)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
240  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
241  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
242  | 
|
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
243  | 
    class Key(private val rep: List[Key.Elem]) {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
244  | 
def +(elem: Key.Elem): Key = Key(rep :+ elem)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
245  | 
def +(i: Int): Key = this + Key.elem(i)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
246  | 
def +(s: String): Key = this + Key.elem(s)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
247  | 
def +(key: Key) = Key(rep ++ key.rep)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
248  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
249  | 
def num: Option[Int] =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
250  | 
        rep match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
251  | 
case (e: Key.List_Elem) :: _ => Some(e.rep)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
252  | 
case _ => None  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
253  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
254  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
255  | 
def get(key: Key): Option[Key] =  | 
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
256  | 
if (!rep.startsWith(key.rep)) None  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
257  | 
        else {
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
258  | 
val rest = rep.drop(key.rep.length)  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
259  | 
if (Key.is_blank(rest)) None  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
260  | 
else Some(Key(rest))  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
261  | 
}  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
262  | 
|
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
263  | 
      def print = rep.map(_.print).mkString("/")
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
264  | 
|
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
265  | 
override def toString: String = print  | 
| 
80104
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
266  | 
override def equals(that: Any): Boolean =  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
267  | 
        that match {
 | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
268  | 
case other: Key => rep == other.rep  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
269  | 
case _ => false  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
270  | 
}  | 
| 
 
138b5172c7f8
clarified web app parameters: more flexible, using HTML5 id specification (nonempty unicode string with no spaces);
 
Fabian Huch <huch@in.tum.de> 
parents: 
80059 
diff
changeset
 | 
271  | 
override def hashCode(): Int = rep.hashCode()  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
272  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
273  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
274  | 
def indexed[A, B](key: Key, xs: List[A], f: (Key, A) => B): List[B] =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
275  | 
for ((x, i) <- xs.zipWithIndex) yield f(key + i, x)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
276  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
277  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
278  | 
    object Data {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
279  | 
      def from_multipart(parts: List[Multi_Part.Data]): Data = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
280  | 
        val files = parts.collect { case f: Multi_Part.File => f }
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
281  | 
val params =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
282  | 
          parts.collect { case Multi_Part.Param(name, value) => Key.explode(name) -> value }
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
283  | 
val file_params = files.map(file => Key.explode(file.name) -> file.file_name)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
284  | 
val file_files = files.map(file => Key.explode(file.name) -> file.content)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
285  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
286  | 
new Data(  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
287  | 
SortedMap.from(params ++ file_params)(Key.Ordering),  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
288  | 
SortedMap.from(file_files)(Key.Ordering))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
289  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
290  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
291  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
292  | 
    class Data private(params: SortedMap[Key, String], files: SortedMap[Key, Bytes]) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
293  | 
      override def toString: String = "Data(" + params.toString() + "," + files.toString() + ")"
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
294  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
295  | 
def get(key: Key): Option[String] = params.get(key)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
296  | 
      def apply(key: Key): String = get(key).getOrElse("")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
297  | 
def list(key: Key): List[Key] =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
298  | 
        (for {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
299  | 
key1 <- params.keys.toList  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
300  | 
key2 <- key1.get(key)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
301  | 
i <- key2.num  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
302  | 
} yield key + i).distinct  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
303  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
304  | 
def file(key: Key): Option[Bytes] = files.get(key)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
305  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
306  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
307  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
308  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
309  | 
/* API with backend base path, and application url (e.g. for frontend links). */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
310  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
311  | 
case class Paths(  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
312  | 
frontend: Url,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
313  | 
api_base: Path,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
314  | 
serve_frontend: Boolean = false,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
315  | 
landing: Path = Path.current  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
316  | 
  ) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
317  | 
def api_path(path: Path, external: Boolean = true): Path =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
318  | 
      (if (serve_frontend) Path.explode("backend") else Path.current) +
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
319  | 
(if (external) api_base else Path.current) + path  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
320  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
321  | 
    def route(path: Path, params: Properties.T = Nil): String = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
322  | 
def param(p: Properties.Entry): String = Url.encode(p._1) + "=" + Url.encode(p._2)  | 
| 
80206
 
3cf3ad092e3e
clarify routes: absolute in api and relative for frontend;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80205 
diff
changeset
 | 
323  | 
      if (params.isEmpty) path.implode else path.implode + "?" + params.map(param).mkString("&")
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
324  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
325  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
326  | 
def api_route(path: Path, params: Properties.T = Nil, external: Boolean = true): String =  | 
| 
80206
 
3cf3ad092e3e
clarify routes: absolute in api and relative for frontend;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80205 
diff
changeset
 | 
327  | 
"/" + route(api_path(path, external = external), params)  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
328  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
329  | 
def frontend_url(path: Path, params: Properties.T = Nil): Url =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
330  | 
frontend.resolve(route(path, params))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
331  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
332  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
333  | 
abstract class Server[A](  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
334  | 
paths: Paths,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
335  | 
port: Int = 0,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
336  | 
verbose: Boolean = false,  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
337  | 
progress: Progress = new Progress(),  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
338  | 
  ) {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
339  | 
def render(model: A): XML.Body  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
340  | 
val error_model: A  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
341  | 
val endpoints: List[API_Endpoint]  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
342  | 
val head: XML.Body  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
343  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
344  | 
|
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
345  | 
/* public-facing endpoints */  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
346  | 
|
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
347  | 
sealed abstract class Endpoint(path: Path, method: String = "GET")  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
348  | 
      extends HTTP.Service(path.implode, method) {
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
349  | 
|
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
350  | 
def reply(request: HTTP.Request): HTTP.Response  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
351  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
352  | 
def html(head: XML.Elem, body: XML.Elem): HTTP.Response =  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
353  | 
HTTP.Response.html(  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
354  | 
cat_lines(  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
355  | 
List(  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
356  | 
HTML.header,  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
357  | 
HTML.output(head, hidden = true, structural = true),  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
358  | 
HTML.output(body, hidden = true, structural = true),  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
359  | 
HTML.footer)))  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
360  | 
|
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
361  | 
final def apply(request: HTTP.Request): Option[HTTP.Response] =  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
362  | 
        Exn.capture(reply(request)) match {
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
363  | 
case Exn.Res(res) => Some(res)  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
364  | 
case Exn.Exn(exn) =>  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
365  | 
val id = UUID.random_string()  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
366  | 
            progress.echo_error_message("Internal error <" + id + ">: " + exn)
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
367  | 
            error("Internal server error. ID: " + id)
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
368  | 
}  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
369  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
370  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
371  | 
    class UI(path: Path) extends Endpoint(path, "GET") {
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
372  | 
      def reply(request: HTTP.Request): HTTP.Response = {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
373  | 
progress.echo_if(verbose, "GET ui")  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
374  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
375  | 
val on_load = """  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
376  | 
(function() {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
377  | 
  window.addEventListener('message', (event) => {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
378  | 
    if (Number.isInteger(event.data)) {
 | 
| 
80249
 
58881e1e4a75
web app: proper document height;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80244 
diff
changeset
 | 
379  | 
this.style.height=event.data + 'px'  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
380  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
381  | 
})  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
382  | 
}).call(this)"""  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
383  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
384  | 
val set_src = """  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
385  | 
const base = '""" + paths.frontend.toString.replace("/", "\\/") + """'
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
386  | 
document.getElementById('iframe').src = base + '""" + paths.api_route(path).replace("/", "\\/") + """' + window.location.search"""
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
387  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
388  | 
html(  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
389  | 
          XML.elem("head", HTML.head_meta :: head),
 | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
390  | 
          XML.Elem(Markup("body", List("style" -> "height: fit-content")), List(
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
391  | 
XML.Elem(  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
392  | 
Markup(  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
393  | 
"iframe",  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
394  | 
List(  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
395  | 
"id" -> "iframe",  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
396  | 
"name" -> "iframe",  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
397  | 
"style" -> "border-style: none; width: 100%",  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
398  | 
"onload" -> on_load)),  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
399  | 
              HTML.text("content")),
 | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
400  | 
HTML.script(set_src))))  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
401  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
402  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
403  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
404  | 
sealed abstract class API_Endpoint(path: Path, method: String = "GET")  | 
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
405  | 
      extends Endpoint(paths.api_path(path, external = false), method) {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
406  | 
|
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
407  | 
      def html_content(content: XML.Body, auto_reload: Boolean = false): HTTP.Response = {
 | 
| 
80256
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
408  | 
        val auto_reload_script = HTML.script("""
 | 
| 80244 | 409  | 
var state = null  | 
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
410  | 
function heartbeat() {
 | 
| 
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
411  | 
  fetch(window.location, { method: "HEAD" }).then((http_res) => {
 | 
| 80244 | 412  | 
    if (http_res.status === 200) {
 | 
413  | 
      const new_state = http_res.headers.get("Content-Digest")
 | 
|
414  | 
if (state === null) state = new_state  | 
|
415  | 
else if (state !== new_state) window.location.reload()  | 
|
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
416  | 
}  | 
| 80244 | 417  | 
setTimeout(heartbeat, 1000)  | 
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
418  | 
})  | 
| 
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
419  | 
}  | 
| 
80256
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
420  | 
heartbeat()""")  | 
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
421  | 
|
| 
80256
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
422  | 
        val resize_script = HTML.script("""
 | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
423  | 
function post_height() {
 | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
424  | 
const scroll_bar_height = window.innerHeight - document.documentElement.clientHeight  | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
425  | 
parent.postMessage(document.documentElement.scrollHeight + scroll_bar_height, '*')  | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
426  | 
}  | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
427  | 
window.addEventListener("resize", (event) => { post_height() })
 | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
428  | 
""")  | 
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
429  | 
|
| 
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
430  | 
val head1 = (if (auto_reload) List(auto_reload_script) else Nil) ::: resize_script :: head  | 
| 
80249
 
58881e1e4a75
web app: proper document height;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80244 
diff
changeset
 | 
431  | 
|
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
432  | 
html(  | 
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
433  | 
          XML.elem("head", HTML.head_meta :: head1),
 | 
| 
80256
 
df8fa0393127
web app: add automatic resize;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80249 
diff
changeset
 | 
434  | 
          XML.Elem(Markup("body", List("onLoad" -> "post_height()")), content))
 | 
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
435  | 
}  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
436  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
437  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
438  | 
    private def query_params(request: HTTP.Request): Properties.T = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
439  | 
def decode(s: String): Option[Properties.Entry] =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
440  | 
        s match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
441  | 
case Properties.Eq(k, v) => Some(Url.decode(k) -> Url.decode(v))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
442  | 
case _ => None  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
443  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
444  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
445  | 
Library.try_unprefix(request.query, request.uri_name).toList.flatMap(params =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
446  | 
        space_explode('&', params).flatMap(decode))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
447  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
448  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
449  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
450  | 
/* endpoint types */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
451  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
452  | 
class Get(val path: Path, description: String, get: Properties.T => Option[A])  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
453  | 
      extends API_Endpoint(path) {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
454  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
455  | 
      def reply(request: HTTP.Request): HTTP.Response = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
456  | 
progress.echo_if(verbose, "GET " + description)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
457  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
458  | 
val params = query_params(request)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
459  | 
progress.echo_if(verbose, "params: " + params.toString())  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
460  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
461  | 
val model =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
462  | 
          get(params) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
463  | 
case Some(model) => model  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
464  | 
case None =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
465  | 
progress.echo_if(verbose, "Parsing failed")  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
466  | 
error_model  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
467  | 
}  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
468  | 
|
| 
80205
 
fc2d791d28bd
add auto-reload for more interactive web apps;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80204 
diff
changeset
 | 
469  | 
html_content(render(model), auto_reload = true)  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
470  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
471  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
472  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
473  | 
class Get_File(path: Path, description: String, download: Properties.T => Option[Path])  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
474  | 
      extends API_Endpoint(path) {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
475  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
476  | 
      def reply(request: HTTP.Request): HTTP.Response = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
477  | 
progress.echo_if(verbose, "DOWNLOAD " + description)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
478  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
479  | 
val params = query_params(request)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
480  | 
progress.echo_if(verbose, "params: " + params.toString())  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
481  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
482  | 
        download(params) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
483  | 
case Some(path) => HTTP.Response.content(HTTP.Content.read(path))  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
484  | 
case None =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
485  | 
progress.echo_if(verbose, "Fetching file path failed")  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
486  | 
html_content(render(error_model))  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
487  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
488  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
489  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
490  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
491  | 
class Post(path: Path, description: String, post: Params.Data => Option[A])  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
492  | 
      extends API_Endpoint(path, method = "POST") {
 | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
493  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
494  | 
      def reply(request: HTTP.Request): HTTP.Response = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
495  | 
progress.echo_if(verbose, "POST " + description)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
496  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
497  | 
val parts = Multi_Part.parse(request.input)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
498  | 
val params = Params.Data.from_multipart(parts)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
499  | 
progress.echo_if(verbose, "params: " + params.toString)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
500  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
501  | 
val model =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
502  | 
          post(params) match {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
503  | 
case Some(model) => model  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
504  | 
case None =>  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
505  | 
progress.echo_if(verbose, "Parsing failed")  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
506  | 
error_model  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
507  | 
}  | 
| 
80204
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
508  | 
|
| 
 
81f2fbf3975d
clarified web app endpoints;
 
Fabian Huch <huch@in.tum.de> 
parents: 
80104 
diff
changeset
 | 
509  | 
html_content(render(model))  | 
| 
80059
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
510  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
511  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
512  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
513  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
514  | 
/* server */  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
515  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
516  | 
private def ui_endpoints =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
517  | 
      if (paths.serve_frontend) endpoints.collect { case page: Get => new UI(page.path) } else Nil
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
518  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
519  | 
private lazy val server =  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
520  | 
HTTP.server(port = port, name = "", services = endpoints ::: ui_endpoints)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
521  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
522  | 
    def run(): Unit = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
523  | 
start()  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
524  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
525  | 
@tailrec  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
526  | 
      def loop(): Unit = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
527  | 
Thread.sleep(Long.MaxValue)  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
528  | 
loop()  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
529  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
530  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
531  | 
      Isabelle_Thread.interrupt_handler(_ => server.stop()) { loop() }
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
532  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
533  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
534  | 
    def start(): Unit = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
535  | 
server.start()  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
536  | 
      progress.echo("Server started on " + paths.frontend_url(paths.landing))
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
537  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
538  | 
|
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
539  | 
    def stop(): Unit = {
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
540  | 
server.stop()  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
541  | 
      progress.echo("Server stopped")
 | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
542  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
543  | 
}  | 
| 
 
37ea0727291f
moved web_app module from AFP (e.g., for building web services for the distributed build);
 
Fabian Huch <huch@in.tum.de> 
parents:  
diff
changeset
 | 
544  | 
}  |