source: trunk/src/rest_interface/set-up-gdl-interface.lisp

Last change on this file was 996, checked in by lgiessmann, 13 years ago

gdl-frontend: updating the hosted javascript files; fixed a bug iun the basic-authentication for the gdl-frontend

File size: 10.5 KB
Line 
1;;+-----------------------------------------------------------------------------
2;;+  Isidorus
3;;+  (c) 2008-2010 Marc Kuester, Christoph Ludwig, Lukas Georgieff
4;;+
5;;+  Isidorus is freely distributable under the LLGPL license.
6;;+  You can find a detailed description in trunk/docs/LLGPL-LICENSE.txt and
7;;+  trunk/docs/LGPL-LICENSE.txt.
8;;+-----------------------------------------------------------------------------
9
10(in-package :rest-interface)
11
12(defparameter *gdl-get-fragment* "/gdl/fragment/(.+)$")
13(defparameter *gdl-get-schema* "/gdl/schema/?$")
14(defparameter *gdl-commit-fragment* "/gdl/commit/?")
15(defparameter *gdl-delete-fragment* "/gdl/delete/?")
16(defparameter *gdl-host-address-hash-object* "/hash-object")
17(defparameter *gdl-host-address-environment* "/environment")
18(defparameter *gdl-base-path* "anaToMia/hosted_files/")
19(defparameter *gdl-host-file* (concat *gdl-base-path* "GDL_Widgets.html"))
20(defparameter *gdl-tm-id* "http://textgrid.org/serviceregistry/gdl-frontend/gdl-tm")
21(defparameter *gdl-sparql* "/gdl/tm-sparql/?$")
22
23
24(defun set-up-gdl-interface (&key (get-fragment *gdl-get-fragment*)
25                             (get-schema *gdl-get-schema*)
26                             (commit-fragment *gdl-commit-fragment*)
27                             (delete-fragment *gdl-delete-fragment*)
28                             (gdl-sparql *gdl-sparql*)
29                             (base-path *gdl-base-path*)
30                             (host-address-hash-object *gdl-host-address-hash-object*)
31                             (host-address-environment *gdl-host-address-environment*)
32                             (host-file *gdl-host-file*))
33  (declare (String get-fragment get-schema commit-fragment
34                   delete-fragment host-address-hash-object
35                   host-address-environment host-file))
36
37  ;(init-cache nil)
38  ;(format t "~%")
39  (init-fragments nil)
40
41  ;; registers the http-code 500 for an internal server error to the standard
42  ;; return codes. so there won't be attached a hunchentoot default message,
43  ;; this is necessary to be able to send error messages in an individual way/syntax
44  ;; e.g. a json error-message.
45  (push hunchentoot:+http-internal-server-error+ hunchentoot:*approved-return-codes*)
46 
47  (init-hosted-files :host-address-hash-object host-address-hash-object
48                     :host-address-environment host-address-environment
49                     :host-file host-file :base-path base-path)
50 
51  (push
52   (create-regex-dispatcher get-fragment
53                            (if (> *use-http-authentication* 2)
54                                (lambda(&optional param)
55                                  (with-http-authentication
56                                      (return-json-fragment-handler param)))
57                                #'return-json-fragment-handler))
58   hunchentoot:*dispatch-table*)
59
60  (push
61   (create-regex-dispatcher get-schema
62                            (if (> *use-http-authentication* 2)
63                                (lambda()
64                                  (with-http-authentication
65                                      (return-gdl-schema-handler)))
66                                #'return-gdl-schema-handler))
67   hunchentoot:*dispatch-table*)
68
69  (push
70   (create-regex-dispatcher commit-fragment
71                            (if (> *use-http-authentication* 1)
72                                (lambda()
73                                  (with-http-authentication
74                                      (commit-fragment-handler)))
75                                #'commit-fragment-handler))
76   hunchentoot:*dispatch-table*)
77
78  (push
79   (create-regex-dispatcher delete-fragment
80                            (if (> *use-http-authentication* 1)
81                                (lambda()
82                                  (with-http-authentication
83                                      (delete-handler)))
84                                #'delete-handler))
85   hunchentoot:*dispatch-table*)
86
87  (push
88   (create-regex-dispatcher gdl-sparql
89                            (if (> *use-http-authentication* 2)
90                                (lambda(&optional param)
91                                  (with-http-authentication
92                                      (gdl-sparql-handler param)))
93                                #'gdl-sparql-handler))
94   hunchentoot:*dispatch-table*))
95
96
97(defun init-hosted-files (&key (host-address-hash-object *gdl-host-address-hash-object*)
98                          (host-address-environment *gdl-host-address-environment*)
99                          (host-file *gdl-host-file*)
100                          (base-path *gdl-base-path*))
101  "Adds handlers for the css, html and js files needed by the frontend."
102  (declare (String host-address-hash-object host-address-environment
103                   host-file base-path))
104  ;; add the actual html file
105  (let ((full-host-path
106         (concat (namestring
107                  (asdf:component-pathname constants:*isidorus-system*))
108                 host-file))
109        (absolute-base-path
110         (concat
111          (namestring
112           (asdf:component-pathname constants:*isidorus-system*))
113          base-path)))
114    (if (> *use-http-authentication* 0)
115        (progn
116          (define-easy-handler (isidorus-ui :uri host-address-hash-object
117                                            :default-request-type :get)
118              ()
119            (with-http-authentication
120                (serve-file full-host-path "text/html")))
121          (define-easy-handler (isidorus-ui :uri host-address-environment
122                                            :default-request-type :get)
123              ()
124            (with-http-authentication
125                (serve-file full-host-path "text/html"))))
126        (progn
127          (push
128           (create-static-file-dispatcher-and-handler
129            host-address-hash-object full-host-path "text/html")
130           hunchentoot:*dispatch-table*)
131          (push
132           (create-static-file-dispatcher-and-handler
133            host-address-environment full-host-path "text/html")
134           hunchentoot:*dispatch-table*)))
135    ; add all additional files
136    (let ((absolute-base-path-len (length absolute-base-path)))
137      (com.gigamonkeys.pathnames:walk-directory
138       "anaToMia/hosted_files"
139       (lambda(item)
140         (unless (or (search "/.svn/" (namestring item) :test #'string=)
141                     (string= full-host-path (namestring item)))
142           (let* ((rel-addr (subseq (namestring item) absolute-base-path-len))
143                  (content-type (generate-content-type (file-namestring item)))
144                  (rel-uri (concat "/" rel-addr)))
145             (push
146              (create-static-file-dispatcher-and-handler
147               rel-uri item content-type)
148              hunchentoot:*dispatch-table*))))))))
149
150
151(defun generate-content-type(file-name)
152  "Returns a mime-type that corresponds to the passed
153   file-ending, note currently onle a fey types are supported!"
154  (declare (String file-name))
155  (cond ((string-ends-with file-name "png" :ignore-case t)
156         "image/png")
157        ((string-ends-with file-name "html" :ignore-case t)
158         "text/html")
159        ((string-ends-with file-name "js" :ignore-case t)
160         "application/json")
161        ((string-ends-with file-name "css" :ignore-case t)
162         "text/css")
163        ((string-ends-with file-name "gif" :ignore-case t)
164         "image/gif")
165        (t
166         "text/plain")))
167
168
169(defun delete-handler()
170  "marks the corresponding construct(s) as deleted"
171  (let ((http-method (hunchentoot:request-method*)))
172    (if (or (eq http-method :DELETE)
173            (eq http-method :POST))
174        (let ((external-format
175               (flexi-streams:make-external-format :UTF-8 :eol-style :LF)))
176          (let ((json-data
177                 (hunchentoot:raw-post-data :external-format external-format
178                                            :force-text t)))
179            (with-writer-lock
180              (let* ((rev (d:get-revision)) 
181                     (result (jtm-delete-interface:mark-as-deleted-from-jtm
182                              json-data :revision rev)))
183                (let ((tops
184                       (remove-null
185                        (cond ((or (typep result 'OccurrenceC)
186                                   (typep result 'NameC))
187                               (let ((top (parent result :revision (1- rev))))
188                                 (when top (list top))))
189                              ((typep result 'VariantC)
190                               (let ((name (parent result :revision (1- rev))))
191                                 (when name
192                                   (let ((top (parent name :revision (1- rev))))
193                                     (when top (list top))))))
194                              ((typep result 'AssociationC)
195                               (map 'list (lambda(role)
196                                            (player role :revision (1- rev)))
197                                    (roles result :revision (1- rev))))
198                              ((typep result 'TopicC)
199                               (let ((assocs
200                                      (remove-null
201                                       (map 'list (lambda(role)
202                                                    (parent role :revision (1- rev)))
203                                            (player-in-roles result :revision (1- rev)))))
204                                     (frags
205                                      (elephant:get-instances-by-value
206                                       'd:FragmentC 'd:topic result)))
207                                 (map nil #'elephant:drop-instance frags)
208                                 (loop for assoc in assocs
209                                    append (map 'list (lambda(role)
210                                                        (player role :revision (1- rev)))
211                                                (roles assoc :revision (1- rev))))))))))
212                  (map nil (lambda(top)
213                             (let ((frags
214                                    (elephant:get-instances-by-value 'd:FragmentC 'd:topic top)))
215                               (map nil #'elephant:drop-instance frags))
216                             (create-latest-fragment-of-topic top))
217                       (if (typep result 'd:TopicC)
218                           (delete result tops)
219                           tops)))
220                (unless result
221                  (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
222                  (format nil "object not found"))))))
223        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
224
225
226(defun commit-fragment-handler ()
227  "handles commits in the JTM 1.1 format."
228  (let ((http-method (hunchentoot:request-method*)))
229    (if (or (eq http-method :PUT)
230            (eq http-method :POST))
231        (let ((external-format
232               (flexi-streams:make-external-format :UTF-8 :eol-style :LF)))
233          (let ((json-data
234                 (hunchentoot:raw-post-data :external-format external-format
235                                            :force-text t)))
236            (with-writer-lock 
237              (jtm-importer:import-construct-from-jtm-string
238               json-data :revision (get-revision) :tm-id *gdl-tm-id*
239               :create-fragments t))))
240        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
241
242
243(defun return-gdl-schema-handler()
244  "Currently the entore topic map is returned.
245   To emerge the efficiency it will be necessary
246   to structure the data as GDL-Fragments, so each view or schema
247   can be served separately."
248  (let ((http-method (hunchentoot:request-method*)))
249    (if (eq http-method :GET)
250        (progn (setf (hunchentoot:content-type*) "application/json")
251               (jtm-exporter:export-as-jtm-string :revision 0))
252        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
253
254
255(defun return-json-fragment-handler(&optional psi)
256  "returns the json-fragmen belonging to the psi passed by the parameter psi"
257  (assert psi)
258  (let ((http-method (hunchentoot:request-method*)))
259    (if (eq http-method :GET)
260        (let ((identifier (hunchentoot:url-decode psi)))
261          (setf (hunchentoot:content-type*) "application/json") ;RFC 4627
262          (let ((fragment
263                 (with-reader-lock
264                   (get-latest-fragment-of-topic identifier))))
265            (if fragment
266                (with-reader-lock
267                  (jtm-exporter:export-construct-as-jtm-string
268                   fragment :revision 0))
269                (progn
270                  (setf (hunchentoot:return-code*) hunchentoot:+http-not-found+)
271                  (setf (hunchentoot:content-type*) "text")
272                  (format nil "Topic \"~a\" not found" psi)))))
273        (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+))))
274
275
276(defun gdl-sparql-handler(&optional param)
277  "Returns a JSON object representing a SPARQL response."
278  (declare (Ignorable param))
279  (if (eql (hunchentoot:request-method*) :POST)
280      (let ((external-format (flexi-streams:make-external-format
281                              :UTF-8 :eol-style :LF)))
282        (let ((sparql-request (hunchentoot:raw-post-data
283                               :external-format external-format
284                               :force-text t)))
285          (export-construct-as-isidorus-json-string
286           (make-instance 'SPARQL-Query :query sparql-request
287                          :revision 0))))
288      (setf (hunchentoot:return-code*) hunchentoot:+http-bad-request+)))
Note: See TracBrowser for help on using the repository browser.