Mercurial > hg > AnnotationManagerN4J
annotate src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java @ 57:4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
author | casties |
---|---|
date | Tue, 20 Nov 2012 17:56:35 +0100 |
parents | a52c597075dc |
children | f5c0e6df7e88 |
rev | line source |
---|---|
3 | 1 /** |
2 * Base class for Annotator resource classes. | |
3 */ | |
4 package de.mpiwg.itgroup.annotations.restlet; | |
5 | |
6 import java.io.UnsupportedEncodingException; | |
7 import java.security.InvalidKeyException; | |
8 import java.security.SignatureException; | |
5 | 9 import java.text.SimpleDateFormat; |
3 | 10 import java.util.ArrayList; |
5 | 11 import java.util.Calendar; |
16 | 12 import java.util.HashSet; |
3 | 13 import java.util.List; |
16 | 14 import java.util.Set; |
3 | 15 import java.util.regex.Matcher; |
16 import java.util.regex.Pattern; | |
17 | |
18 import net.oauth.jsontoken.Checker; | |
19 import net.oauth.jsontoken.JsonToken; | |
20 import net.oauth.jsontoken.JsonTokenParser; | |
21 import net.oauth.jsontoken.SystemClock; | |
22 import net.oauth.jsontoken.crypto.HmacSHA256Verifier; | |
23 import net.oauth.jsontoken.crypto.Verifier; | |
24 | |
25 import org.apache.commons.codec.binary.Base64; | |
26 import org.apache.log4j.Logger; | |
27 import org.json.JSONArray; | |
28 import org.json.JSONException; | |
29 import org.json.JSONObject; | |
30 import org.restlet.data.Form; | |
31 import org.restlet.data.Status; | |
32 import org.restlet.representation.Representation; | |
33 import org.restlet.resource.Options; | |
34 import org.restlet.resource.ServerResource; | |
35 | |
9 | 36 import de.mpiwg.itgroup.annotations.Actor; |
4 | 37 import de.mpiwg.itgroup.annotations.Annotation; |
38 import de.mpiwg.itgroup.annotations.Annotation.FragmentTypes; | |
10 | 39 import de.mpiwg.itgroup.annotations.Group; |
19 | 40 import de.mpiwg.itgroup.annotations.NS; |
10 | 41 import de.mpiwg.itgroup.annotations.Person; |
48
0e00bf8e27fb
targets and resources of Annotation object are objects now.
casties
parents:
40
diff
changeset
|
42 import de.mpiwg.itgroup.annotations.Resource; |
0e00bf8e27fb
targets and resources of Annotation object are objects now.
casties
parents:
40
diff
changeset
|
43 import de.mpiwg.itgroup.annotations.Target; |
4 | 44 import de.mpiwg.itgroup.annotations.neo4j.AnnotationStore; |
3 | 45 |
46 /** | |
47 * Base class for Annotator resource classes. | |
48 * | |
49 * @author dwinter, casties | |
50 * | |
51 */ | |
52 public abstract class AnnotatorResourceImpl extends ServerResource { | |
53 | |
4 | 54 protected static Logger logger = Logger.getLogger(AnnotatorResourceImpl.class); |
55 | |
56 private AnnotationStore store; | |
3 | 57 |
58 protected String getAllowedMethodsForHeader() { | |
59 return "OPTIONS,GET,POST"; | |
60 } | |
61 | |
4 | 62 protected AnnotationStore getAnnotationStore() { |
63 if (store == null) { | |
19 | 64 store = ((BaseRestlet) getApplication()).getAnnotationStore(); |
4 | 65 } |
66 return store; | |
67 } | |
68 | |
3 | 69 public String encodeJsonId(String id) { |
22 | 70 if (id == null) return null; |
3 | 71 try { |
72 return Base64.encodeBase64URLSafeString(id.getBytes("UTF-8")); | |
73 } catch (UnsupportedEncodingException e) { | |
74 return null; | |
75 } | |
76 } | |
77 | |
78 public String decodeJsonId(String id) { | |
22 | 79 if (id == null) return null; |
3 | 80 try { |
81 return new String(Base64.decodeBase64(id), "UTF-8"); | |
82 } catch (UnsupportedEncodingException e) { | |
83 return null; | |
84 } | |
85 } | |
86 | |
87 /** | |
88 * Handle options request to allow CORS for AJAX. | |
89 * | |
90 * @param entity | |
91 */ | |
92 @Options | |
93 public void doOptions(Representation entity) { | |
94 logger.debug("AnnotatorResourceImpl doOptions!"); | |
95 setCorsHeaders(); | |
96 } | |
97 | |
98 /** | |
99 * set headers to allow CORS for AJAX. | |
100 */ | |
101 protected void setCorsHeaders() { | |
102 Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers"); | |
103 if (responseHeaders == null) { | |
104 responseHeaders = new Form(); | |
105 getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders); | |
106 } | |
107 responseHeaders.add("Access-Control-Allow-Methods", getAllowedMethodsForHeader()); | |
108 // echo back Origin and Request-Headers | |
109 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers"); | |
110 String origin = requestHeaders.getFirstValue("Origin", true); | |
111 if (origin == null) { | |
112 responseHeaders.add("Access-Control-Allow-Origin", "*"); | |
113 } else { | |
114 responseHeaders.add("Access-Control-Allow-Origin", origin); | |
115 } | |
116 String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true); | |
117 if (allowHeaders != null) { | |
118 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders); | |
119 } | |
120 responseHeaders.add("Access-Control-Allow-Credentials", "true"); | |
121 responseHeaders.add("Access-Control-Max-Age", "60"); | |
122 } | |
123 | |
124 /** | |
125 * returns if authentication information from headers is valid. | |
126 * | |
127 * @param entity | |
128 * @return | |
129 */ | |
130 public boolean isAuthenticated(Representation entity) { | |
131 return (checkAuthToken(entity) != null); | |
132 } | |
133 | |
134 /** | |
57
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
135 * Checks Annotator Auth plugin authentication information from headers. |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
136 * Returns userId if successful. Returns "anonymous" in non-authorization mode. |
3 | 137 * |
138 * @param entity | |
139 * @return | |
140 */ | |
141 public String checkAuthToken(Representation entity) { | |
142 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers"); | |
143 String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true); | |
57
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
144 if (authToken == null) { |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
145 if (!((BaseRestlet) getApplication()).isAuthorizationMode()) { |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
146 return "anonymous"; |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
147 } |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
148 return null; |
4efb21cf0ce0
new non-authorized mode without tokens. enabled by default. configured with annotationmanager.authorization=false property.
casties
parents:
52
diff
changeset
|
149 } |
3 | 150 // decode token first to get consumer key |
151 JsonToken token = new JsonTokenParser(null, null).deserialize(authToken); | |
152 String userId = token.getParamAsPrimitive("userId").getAsString(); | |
153 String consumerKey = token.getParamAsPrimitive("consumerKey").getAsString(); | |
154 // get stored consumer secret for key | |
18 | 155 BaseRestlet restServer = (BaseRestlet) getApplication(); |
3 | 156 String consumerSecret = restServer.getConsumerSecret(consumerKey); |
157 logger.debug("requested consumer key=" + consumerKey + " secret=" + consumerSecret); | |
158 if (consumerSecret == null) { | |
159 return null; | |
160 } | |
161 // logger.debug(String.format("token=%s tokenString=%s signatureAlgorithm=%s",token,token.getTokenString(),token.getSignatureAlgorithm())); | |
162 try { | |
163 List<Verifier> verifiers = new ArrayList<Verifier>(); | |
164 // we only do HS256 yet | |
165 verifiers.add(new HmacSHA256Verifier(consumerSecret.getBytes("UTF-8"))); | |
166 // verify token signature(should really be static...) | |
167 new JsonTokenParser(new SystemClock(), null, (Checker[]) null).verify(token, verifiers); | |
168 } catch (SignatureException e) { | |
169 // TODO Auto-generated catch block | |
170 e.printStackTrace(); | |
171 } catch (InvalidKeyException e) { | |
172 // TODO Auto-generated catch block | |
173 e.printStackTrace(); | |
174 } catch (UnsupportedEncodingException e) { | |
175 // TODO Auto-generated catch block | |
176 e.printStackTrace(); | |
177 } | |
178 // must be ok then | |
179 logger.debug("auth OK! user=" + userId); | |
180 return userId; | |
181 } | |
182 | |
183 /** | |
184 * creates Annotator-JSON from an Annotation object. | |
185 * | |
186 * @param annot | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
187 * @param forAnonymous TODO |
3 | 188 * @return |
189 */ | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
190 public JSONObject createAnnotatorJson(Annotation annot, boolean forAnonymous) { |
5 | 191 // return user as a JSON object (otherwise just as string) |
3 | 192 boolean makeUserObject = true; |
193 JSONObject jo = new JSONObject(); | |
194 try { | |
4 | 195 jo.put("text", annot.getBodyText()); |
196 jo.put("uri", annot.getTargetBaseUri()); | |
40
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
197 if (annot.getResourceUri() != null) { |
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
198 jo.put("resource", annot.getResourceUri()); |
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
199 } |
3 | 200 |
16 | 201 /* |
202 * user | |
203 */ | |
3 | 204 if (makeUserObject) { |
205 // create user object | |
206 JSONObject userObject = new JSONObject(); | |
10 | 207 Actor creator = annot.getCreator(); |
3 | 208 // save creator as uri |
10 | 209 userObject.put("uri", creator.getUri()); |
3 | 210 // make short user id |
10 | 211 String userId = creator.getIdString(); |
9 | 212 // set as id |
4 | 213 userObject.put("id", userId); |
3 | 214 // get full name |
10 | 215 String userName = creator.getName(); |
5 | 216 if (userName == null) { |
18 | 217 BaseRestlet restServer = (BaseRestlet) getApplication(); |
5 | 218 userName = restServer.getFullNameFromLdap(userId); |
219 } | |
3 | 220 userObject.put("name", userName); |
221 // save user object | |
222 jo.put("user", userObject); | |
223 } else { | |
224 // save user as string | |
4 | 225 jo.put("user", annot.getCreatorUri()); |
3 | 226 } |
227 | |
16 | 228 /* |
229 * ranges | |
230 */ | |
4 | 231 if (annot.getTargetFragment() != null) { |
3 | 232 // we only look at the first xpointer |
4 | 233 List<String> fragments = new ArrayList<String>(); |
234 fragments.add(annot.getTargetFragment()); | |
235 FragmentTypes xt = annot.getFragmentType(); | |
236 if (xt == FragmentTypes.XPOINTER) { | |
237 jo.put("ranges", transformToRanges(fragments)); | |
238 } else if (xt == FragmentTypes.AREA) { | |
239 jo.put("areas", transformToAreas(fragments)); | |
3 | 240 } |
241 } | |
10 | 242 |
16 | 243 /* |
244 * permissions | |
245 */ | |
10 | 246 JSONObject perms = new JSONObject(); |
247 jo.put("permissions", perms); | |
248 // admin | |
249 JSONArray adminPerms = new JSONArray(); | |
250 perms.put("admin", adminPerms); | |
251 Actor adminPerm = annot.getAdminPermission(); | |
252 if (adminPerm != null) { | |
253 adminPerms.put(adminPerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
254 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
255 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
256 adminPerms.put("not-you"); |
10 | 257 } |
258 // delete | |
259 JSONArray deletePerms = new JSONArray(); | |
260 perms.put("delete", deletePerms); | |
261 Actor deletePerm = annot.getDeletePermission(); | |
262 if (deletePerm != null) { | |
263 deletePerms.put(deletePerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
264 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
265 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
266 deletePerms.put("not-you"); |
10 | 267 } |
268 // update | |
269 JSONArray updatePerms = new JSONArray(); | |
270 perms.put("update", updatePerms); | |
271 Actor updatePerm = annot.getUpdatePermission(); | |
272 if (updatePerm != null) { | |
273 updatePerms.put(updatePerm.getIdString()); | |
14
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
274 } else if (forAnonymous) { |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
275 // set something because its not allowed for anonymous |
629e15b345aa
permissions mostly work. need more server-side checking.
casties
parents:
10
diff
changeset
|
276 updatePerms.put("not-you"); |
10 | 277 } |
278 // read | |
279 JSONArray readPerms = new JSONArray(); | |
280 perms.put("read", readPerms); | |
281 Actor readPerm = annot.getReadPermission(); | |
282 if (readPerm != null) { | |
283 readPerms.put(readPerm.getIdString()); | |
284 } | |
285 | |
16 | 286 /* |
287 * tags | |
288 */ | |
289 Set<String> tagset = annot.getTags(); | |
290 if (tagset != null) { | |
291 JSONArray tags = new JSONArray(); | |
292 jo.put("tags", tags); | |
293 for (String tag : tagset) { | |
294 tags.put(tag); | |
295 } | |
296 } | |
297 | |
298 /* | |
299 * id | |
300 */ | |
3 | 301 // encode Annotation URL (=id) in base64 |
4 | 302 String annotUrl = annot.getUri(); |
3 | 303 String annotId = encodeJsonId(annotUrl); |
304 jo.put("id", annotId); | |
305 return jo; | |
306 } catch (JSONException e) { | |
307 // TODO Auto-generated catch block | |
308 e.printStackTrace(); | |
309 } | |
310 return null; | |
311 } | |
312 | |
313 private JSONArray transformToRanges(List<String> xpointers) { | |
314 | |
315 JSONArray ja = new JSONArray(); | |
316 | |
317 Pattern rg = Pattern | |
4 | 318 .compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)"); |
319 Pattern rg1 = Pattern.compile("xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)"); | |
3 | 320 |
321 try { | |
322 for (String xpointer : xpointers) { | |
10 | 323 // String decoded = URLDecoder.decode(xpointer, "utf-8"); |
5 | 324 String decoded = xpointer; |
3 | 325 Matcher m = rg.matcher(decoded); |
326 | |
327 if (m.find()) { | |
328 { | |
329 JSONObject jo = new JSONObject(); | |
330 jo.put("start", m.group(1)); | |
331 jo.put("startOffset", m.group(2)); | |
332 jo.put("end", m.group(3)); | |
333 jo.put("endOffset", m.group(4)); | |
334 ja.put(jo); | |
335 } | |
336 } | |
337 m = rg1.matcher(xpointer); | |
338 if (m.find()) { | |
339 JSONObject jo = new JSONObject(); | |
340 jo.put("start", m.group(1)); | |
341 jo.put("startOffset", m.group(2)); | |
342 | |
343 ja.put(jo); | |
344 } | |
345 } | |
346 } catch (JSONException e) { | |
347 // TODO Auto-generated catch block | |
348 e.printStackTrace(); | |
349 } | |
350 return ja; | |
351 } | |
352 | |
353 private JSONArray transformToAreas(List<String> xpointers) { | |
354 | |
355 JSONArray ja = new JSONArray(); | |
356 | |
4 | 357 Pattern rg = Pattern.compile("xywh=(\\w*:)([\\d\\.]+),([\\d\\.]+),([\\d\\.]+),([\\d\\.]+)"); |
3 | 358 |
359 try { | |
360 for (String xpointer : xpointers) { | |
10 | 361 // String decoded = URLDecoder.decode(xpointer, "utf-8"); |
5 | 362 String decoded = xpointer; |
3 | 363 Matcher m = rg.matcher(decoded); |
364 | |
365 if (m.find()) { | |
366 { | |
367 JSONObject jo = new JSONObject(); | |
10 | 368 @SuppressWarnings("unused") |
3 | 369 String unit = m.group(1); |
370 jo.put("x", m.group(2)); | |
371 jo.put("y", m.group(3)); | |
372 jo.put("width", m.group(4)); | |
373 jo.put("height", m.group(5)); | |
374 ja.put(jo); | |
375 } | |
376 } | |
377 } | |
378 } catch (JSONException e) { | |
379 // TODO Auto-generated catch block | |
380 e.printStackTrace(); | |
381 } | |
382 return ja; | |
383 } | |
384 | |
5 | 385 protected String parseArea(JSONObject area) throws JSONException { |
4 | 386 String x = area.getString("x"); |
387 String y = area.getString("y"); | |
388 String width = "0"; | |
389 String height = "0"; | |
390 if (area.has("width")) { | |
391 width = area.getString("width"); | |
392 height = area.getString("height"); | |
393 } | |
5 | 394 String fragment = String.format("xywh=fraction:%s,%s,%s,%s", x, y, width, height); |
4 | 395 return fragment; |
396 } | |
397 | |
5 | 398 protected String parseRange(JSONObject range) throws JSONException { |
4 | 399 String start = range.getString("start"); |
400 String end = range.getString("end"); | |
401 String startOffset = range.getString("startOffset"); | |
402 String endOffset = range.getString("endOffset"); | |
403 | |
5 | 404 String fragment = String.format( |
4 | 405 "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))", start, |
5 | 406 startOffset, end, endOffset); |
4 | 407 return fragment; |
408 } | |
409 | |
3 | 410 /** |
5 | 411 * Creates an Annotation object with data from JSON. |
3 | 412 * |
4 | 413 * uses the specification from the annotator project: {@link https |
414 * ://github.com/okfn/annotator/wiki/Annotation-format} | |
3 | 415 * |
4 | 416 * The username will be transformed to an URI if not given already as URI, |
417 * if not it will set to the MPIWG namespace defined in | |
3 | 418 * de.mpiwg.itgroup.annotationManager.Constants.NS |
419 * | |
420 * @param jo | |
421 * @return | |
422 * @throws JSONException | |
4 | 423 * @throws UnsupportedEncodingException |
3 | 424 */ |
4 | 425 public Annotation createAnnotation(JSONObject jo, Representation entity) throws JSONException, UnsupportedEncodingException { |
3 | 426 return updateAnnotation(new Annotation(), jo, entity); |
427 } | |
428 | |
5 | 429 /** |
430 * Updates an Annotation object with data from JSON. | |
431 * | |
432 * uses the specification from the annotator project: {@link https | |
433 * ://github.com/okfn/annotator/wiki/Annotation-format} | |
434 * | |
435 * The username will be transformed to an URI if not given already as URI, | |
436 * if not it will set to the MPIWG namespace defined in | |
437 * de.mpiwg.itgroup.annotationManager.Constants.NS | |
438 * | |
439 * @param annot | |
440 * @param jo | |
441 * @return | |
442 * @throws JSONException | |
443 * @throws UnsupportedEncodingException | |
444 */ | |
4 | 445 public Annotation updateAnnotation(Annotation annot, JSONObject jo, Representation entity) throws JSONException, |
446 UnsupportedEncodingException { | |
16 | 447 /* |
448 * target uri | |
449 */ | |
3 | 450 if (jo.has("uri")) { |
48
0e00bf8e27fb
targets and resources of Annotation object are objects now.
casties
parents:
40
diff
changeset
|
451 annot.setTarget(new Target(jo.getString("uri"))); |
3 | 452 } |
16 | 453 /* |
40
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
454 * resource uri |
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
455 */ |
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
456 if (jo.has("resource")) { |
48
0e00bf8e27fb
targets and resources of Annotation object are objects now.
casties
parents:
40
diff
changeset
|
457 annot.setResource(new Resource(jo.getString("resource"))); |
40
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
458 } |
03e0f7574224
saving and loading resource targets should work now (no searching yet)
casties
parents:
22
diff
changeset
|
459 /* |
16 | 460 * annotation text |
461 */ | |
3 | 462 if (jo.has("text")) { |
4 | 463 annot.setBodyText(jo.getString("text")); |
3 | 464 } |
16 | 465 /* |
466 * check authentication | |
467 */ | |
3 | 468 String authUser = checkAuthToken(entity); |
469 if (authUser == null) { | |
4 | 470 /* |
471 * // try http auth User httpUser = getHttpAuthUser(entity); if | |
472 * (httpUser == null) { | |
473 */ | |
474 setStatus(Status.CLIENT_ERROR_FORBIDDEN); | |
475 return null; | |
476 /* | |
477 * } authUser = httpUser.getIdentifier(); | |
478 */ | |
3 | 479 } |
16 | 480 /* |
481 * get or create creator object | |
482 */ | |
9 | 483 Actor creator = annot.getCreator(); |
484 if (creator == null) { | |
10 | 485 creator = new Person(); |
9 | 486 annot.setCreator(creator); |
487 } | |
3 | 488 // username not required, if no username given authuser will be used |
489 String username = null; | |
10 | 490 String userUri = creator.getUri(); |
3 | 491 if (jo.has("user")) { |
492 if (jo.get("user") instanceof String) { | |
493 // user is just a String | |
494 username = jo.getString("user"); | |
10 | 495 creator.setId(username); |
3 | 496 // TODO: what if username and authUser are different? |
497 } else { | |
498 // user is an object | |
499 JSONObject user = jo.getJSONObject("user"); | |
500 if (user.has("id")) { | |
10 | 501 String id = user.getString("id"); |
502 creator.setId(id); | |
503 username = id; | |
3 | 504 } |
505 if (user.has("uri")) { | |
506 userUri = user.getString("uri"); | |
507 } | |
508 } | |
509 } | |
510 if (username == null) { | |
511 username = authUser; | |
512 } | |
5 | 513 // try to get full name |
9 | 514 if (creator.getName() == null && username != null) { |
18 | 515 BaseRestlet restServer = (BaseRestlet) getApplication(); |
5 | 516 String fullName = restServer.getFullNameFromLdap(username); |
9 | 517 creator.setName(fullName); |
5 | 518 } |
519 // userUri should be a URI, if not it will set to the MPIWG namespace | |
3 | 520 if (userUri == null) { |
521 if (username.startsWith("http")) { | |
522 userUri = username; | |
523 } else { | |
524 userUri = NS.MPIWG_PERSONS_URL + username; | |
525 } | |
526 } | |
527 // TODO: should we overwrite the creator? | |
9 | 528 if (creator.getUri() == null) { |
529 creator.setUri(userUri); | |
5 | 530 } |
16 | 531 /* |
532 * creation date | |
533 */ | |
5 | 534 if (annot.getCreated() == null) { |
535 // set creation date | |
536 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); | |
537 String ct = format.format(Calendar.getInstance().getTime()); | |
538 annot.setCreated(ct); | |
539 } | |
3 | 540 |
16 | 541 /* |
542 * create xpointer from the first range/area | |
543 */ | |
52 | 544 try { |
545 if (jo.has("ranges")) { | |
546 JSONObject ranges = jo.getJSONArray("ranges").getJSONObject(0); | |
547 annot.setFragmentType(FragmentTypes.XPOINTER); | |
548 String fragment = parseRange(ranges); | |
549 annot.setTargetFragment(fragment); | |
550 } | |
551 } catch (JSONException e) { | |
552 // nothing to do | |
3 | 553 } |
52 | 554 try { |
555 if (jo.has("areas")) { | |
556 JSONObject area = jo.getJSONArray("areas").getJSONObject(0); | |
557 annot.setFragmentType(FragmentTypes.AREA); | |
558 String fragment = parseArea(area); | |
559 annot.setTargetFragment(fragment); | |
560 } | |
561 } catch (JSONException e) { | |
562 // nothing to do | |
3 | 563 } |
10 | 564 |
16 | 565 /* |
566 * permissions | |
567 */ | |
10 | 568 if (jo.has("permissions")) { |
569 JSONObject permissions = jo.getJSONObject("permissions"); | |
570 if (permissions.has("admin")) { | |
571 JSONArray perms = permissions.getJSONArray("admin"); | |
572 Actor actor = getActorFromPermissions(perms); | |
573 annot.setAdminPermission(actor); | |
574 } | |
575 if (permissions.has("delete")) { | |
576 JSONArray perms = permissions.getJSONArray("delete"); | |
577 Actor actor = getActorFromPermissions(perms); | |
578 annot.setDeletePermission(actor); | |
579 } | |
580 if (permissions.has("update")) { | |
581 JSONArray perms = permissions.getJSONArray("update"); | |
582 Actor actor = getActorFromPermissions(perms); | |
583 annot.setUpdatePermission(actor); | |
584 } | |
585 if (permissions.has("read")) { | |
586 JSONArray perms = permissions.getJSONArray("read"); | |
587 Actor actor = getActorFromPermissions(perms); | |
588 annot.setReadPermission(actor); | |
589 } | |
590 } | |
591 | |
16 | 592 /* |
593 * tags | |
594 */ | |
595 if (jo.has("tags")) { | |
596 HashSet<String> tagset = new HashSet<String>(); | |
597 JSONArray tags = jo.getJSONArray("tags"); | |
598 for (int i = 0; i < tags.length(); ++i) { | |
599 tagset.add(tags.getString(i)); | |
600 } | |
601 annot.setTags(tagset); | |
602 } | |
603 | |
604 | |
4 | 605 return annot; |
3 | 606 } |
607 | |
15 | 608 @SuppressWarnings("unused") // i in for loop |
10 | 609 protected Actor getActorFromPermissions(JSONArray perms) throws JSONException { |
610 Actor actor = null; | |
611 for (int i = 0; i < perms.length(); ++i) { | |
612 String perm = perms.getString(i); | |
613 if (perm.toLowerCase().startsWith("group:")) { | |
614 String groupId = perm.substring(6); | |
615 actor = new Group(groupId); | |
616 } else { | |
617 actor = new Person(perm); | |
618 } | |
619 // we just take the first one | |
620 break; | |
621 } | |
622 return actor; | |
623 } | |
624 | |
3 | 625 } |