annotate src/main/java/de/mpiwg/itgroup/annotationManager/restlet/AnnotatorResourceImpl.java @ 26:235b91ba8dff

on the way to new annotations...
author casties
date Thu, 26 Apr 2012 11:44:57 +0200
parents d9809412b67f
children 40846c0b344d
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
1 /**
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
2 * Base class for Annotator resource classes.
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
3 */
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
4 package de.mpiwg.itgroup.annotationManager.restlet;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
5
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
6 import java.io.UnsupportedEncodingException;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
7 import java.net.URLDecoder;
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
8 import java.net.URLEncoder;
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
9 import java.security.InvalidKeyException;
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
10 import java.security.SignatureException;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
11 import java.util.ArrayList;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
12 import java.util.List;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
13 import java.util.regex.Matcher;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
14 import java.util.regex.Pattern;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
15
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
16 import net.oauth.jsontoken.Checker;
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
17 import net.oauth.jsontoken.JsonToken;
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
18 import net.oauth.jsontoken.JsonTokenParser;
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
19 import net.oauth.jsontoken.SystemClock;
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
20 import net.oauth.jsontoken.crypto.HmacSHA256Verifier;
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
21 import net.oauth.jsontoken.crypto.Verifier;
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
22
24
d9809412b67f fixed setup.
casties
parents: 23
diff changeset
23 import org.apache.commons.codec.binary.Base64;
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
24 import org.apache.log4j.Logger;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
25 import org.json.JSONArray;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
26 import org.json.JSONException;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
27 import org.json.JSONObject;
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
28 import org.restlet.data.ClientInfo;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
29 import org.restlet.data.Form;
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
30 import org.restlet.data.Status;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
31 import org.restlet.representation.Representation;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
32 import org.restlet.resource.Options;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
33 import org.restlet.resource.ServerResource;
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
34 import org.restlet.security.User;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
35
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
36 import de.mpiwg.itgroup.annotationManager.Constants.NS;
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
37 import de.mpiwg.itgroup.annotationManager.RDFHandling.Annotation;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
38
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
39 /**
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
40 * Base class for Annotator resource classes.
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
41 *
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
42 * @author dwinter, casties
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
43 *
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
44 */
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
45 public abstract class AnnotatorResourceImpl extends ServerResource {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
46
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
47 protected Logger logger = Logger.getRootLogger();
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
48
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
49 protected String getAllowedMethodsForHeader() {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
50 return "OPTIONS,GET,POST";
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
51 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
52
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
53 public String encodeJsonId(String id) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
54 try {
24
d9809412b67f fixed setup.
casties
parents: 23
diff changeset
55 return Base64.encodeBase64URLSafeString(id.getBytes("UTF-8"));
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
56 } catch (UnsupportedEncodingException e) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
57 return null;
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
58 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
59 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
60
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
61 public String decodeJsonId(String id) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
62 try {
24
d9809412b67f fixed setup.
casties
parents: 23
diff changeset
63 return new String(Base64.decodeBase64(id), "UTF-8");
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
64 } catch (UnsupportedEncodingException e) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
65 return null;
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
66 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
67 }
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
68
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
69 /**
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
70 * Handle options request to allow CORS for AJAX.
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
71 *
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
72 * @param entity
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
73 */
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
74 @Options
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
75 public void doOptions(Representation entity) {
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
76 logger.debug("AnnotatorResourceImpl doOptions!");
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
77 setCorsHeaders();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
78 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
79
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
80 /**
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
81 * set headers to allow CORS for AJAX.
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
82 */
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
83 protected void setCorsHeaders() {
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
84 Form responseHeaders = (Form) getResponse().getAttributes().get("org.restlet.http.headers");
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
85 if (responseHeaders == null) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
86 responseHeaders = new Form();
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
87 getResponse().getAttributes().put("org.restlet.http.headers", responseHeaders);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
88 }
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
89 responseHeaders.add("Access-Control-Allow-Methods", getAllowedMethodsForHeader());
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
90 // echo back Origin and Request-Headers
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
91 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
92 String origin = requestHeaders.getFirstValue("Origin", true);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
93 if (origin == null) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
94 responseHeaders.add("Access-Control-Allow-Origin", "*");
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
95 } else {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
96 responseHeaders.add("Access-Control-Allow-Origin", origin);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
97 }
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
98 String allowHeaders = requestHeaders.getFirstValue("Access-Control-Request-Headers", true);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
99 if (allowHeaders != null) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
100 responseHeaders.add("Access-Control-Allow-Headers", allowHeaders);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
101 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
102 responseHeaders.add("Access-Control-Allow-Credentials", "true");
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
103 responseHeaders.add("Access-Control-Max-Age", "60");
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
104 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
105
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
106 /**
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
107 * returns if authentication information from headers is valid.
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
108 *
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
109 * @param entity
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
110 * @return
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
111 */
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
112 public boolean isAuthenticated(Representation entity) {
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
113 return (checkAuthToken(entity) != null);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
114 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
115
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
116 /**
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
117 * checks Annotator Auth plugin authentication information from headers. returns userId if successful.
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
118 *
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
119 * @param entity
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
120 * @return
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
121 */
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
122 public String checkAuthToken(Representation entity) {
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
123 Form requestHeaders = (Form) getRequest().getAttributes().get("org.restlet.http.headers");
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
124 String authToken = requestHeaders.getFirstValue("x-annotator-auth-token", true);
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
125 // decode token first to get consumer key
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
126 JsonToken token = new JsonTokenParser(null, null).deserialize(authToken);
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
127 String userId = token.getParamAsPrimitive("userId").getAsString();
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
128 String consumerKey = token.getParamAsPrimitive("consumerKey").getAsString();
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
129 // get stored consumer secret for key
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
130 RestServer restServer = (RestServer) getApplication();
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
131 String consumerSecret = restServer.getConsumerSecret(consumerKey);
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
132 logger.debug("requested consumer key=" + consumerKey + " secret=" + consumerSecret);
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
133 if (consumerSecret == null) {
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
134 return null;
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
135 }
21
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
136 //logger.debug(String.format("token=%s tokenString=%s signatureAlgorithm=%s",token,token.getTokenString(),token.getSignatureAlgorithm()));
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
137 try {
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
138 List<Verifier> verifiers = new ArrayList<Verifier>();
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
139 // we only do HS256 yet
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
140 verifiers.add(new HmacSHA256Verifier(consumerSecret.getBytes("UTF-8")));
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
141 // verify token signature(should really be static...)
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
142 new JsonTokenParser(new SystemClock(), null, (Checker[]) null).verify(token, verifiers);
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
143 } catch (SignatureException e) {
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
144 // TODO Auto-generated catch block
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
145 e.printStackTrace();
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
146 } catch (InvalidKeyException e) {
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
147 // TODO Auto-generated catch block
0cd1e7608d25 works with new JWT-Auth now!
casties
parents: 20
diff changeset
148 e.printStackTrace();
20
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
149 } catch (UnsupportedEncodingException e) {
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
150 // TODO Auto-generated catch block
6629e8422760 half baked version for new JWT auth :-(
casties
parents: 17
diff changeset
151 e.printStackTrace();
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
152 }
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
153 // must be ok then
15
6c7c4140630d on the way to updating annotations.
casties
parents: 14
diff changeset
154 logger.debug("auth OK! user="+userId);
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
155 return userId;
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
156 }
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
157
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
158 /**
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
159 * creates Annotator-JSON from an Annotation object.
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
160 *
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
161 * @param annot
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
162 * @return
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
163 */
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
164 public JSONObject createAnnotatorJson(Annotation annot) {
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
165 boolean makeUserObject = true;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
166 JSONObject jo = new JSONObject();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
167 try {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
168 jo.put("text", annot.text);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
169 jo.put("uri", annot.url);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
170
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
171 if (makeUserObject) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
172 // create user object
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
173 JSONObject userObject = new JSONObject();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
174 // save creator as uri
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
175 userObject.put("uri", annot.creator);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
176 // make short user id
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
177 String userID = annot.creator;
26
235b91ba8dff on the way to new annotations...
casties
parents: 24
diff changeset
178 if (userID.startsWith(NS.MPIWG_PERSONS_URL)) {
235b91ba8dff on the way to new annotations...
casties
parents: 24
diff changeset
179 userID = userID.replace(NS.MPIWG_PERSONS_URL, ""); // entferne NAMESPACE
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
180 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
181 // save as id
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
182 userObject.put("id", userID);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
183 // get full name
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
184 RestServer restServer = (RestServer) getApplication();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
185 String userName = restServer.getUserNameFromLdap(userID);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
186 userObject.put("name", userName);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
187 // save user object
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
188 jo.put("user", userObject);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
189 } else {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
190 // save user as string
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
191 jo.put("user", annot.creator);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
192 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
193
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
194 List<String> xpointers = new ArrayList<String>();
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
195 if (annot.xpointers == null || annot.xpointers.size() == 0)
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
196 xpointers.add(annot.xpointer);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
197 else {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
198 for (String xpointerString : annot.xpointers) {
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
199 xpointers.add(xpointerString);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
200 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
201 }
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
202 jo.put("ranges", transformToRanges(xpointers));
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
203 // encode Annotation URL (=id) in base64
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
204 String annotUrl = annot.getAnnotationUri();
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
205 String annotId = encodeJsonId(annotUrl);
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
206 jo.put("id", annotId);
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
207 return jo;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
208 } catch (JSONException e) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
209 // TODO Auto-generated catch block
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
210 e.printStackTrace();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
211 }
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
212 return null;
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
213 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
214
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
215 private JSONArray transformToRanges(List<String> xpointers) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
216
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
217 JSONArray ja = new JSONArray();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
218
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
219 Pattern rg = Pattern
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
220 .compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)/range-to\\(end-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)\\)");
10
0bdfe01e30b5 checking auth token works now.
casties
parents: 8
diff changeset
221 Pattern rg1 = Pattern.compile("#xpointer\\(start-point\\(string-range\\(\"([^\"]*)\",([^,]*),1\\)\\)\\)");
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
222
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
223 try {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
224 for (String xpointer : xpointers) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
225 String decoded = URLDecoder.decode(xpointer, "utf-8");
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
226 Matcher m = rg.matcher(decoded);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
227
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
228 if (m.find()) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
229 {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
230 JSONObject jo = new JSONObject();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
231 jo.put("start", m.group(1));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
232 jo.put("startOffset", m.group(2));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
233 jo.put("end", m.group(3));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
234 jo.put("endOffset", m.group(4));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
235 ja.put(jo);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
236 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
237 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
238 m = rg1.matcher(xpointer);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
239 if (m.find()) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
240 JSONObject jo = new JSONObject();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
241 jo.put("start", m.group(1));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
242 jo.put("startOffset", m.group(2));
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
243
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
244 ja.put(jo);
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
245 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
246 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
247 } catch (JSONException e) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
248 // TODO Auto-generated catch block
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
249 e.printStackTrace();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
250 } catch (UnsupportedEncodingException e) {
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
251 // TODO Auto-generated catch block
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
252 e.printStackTrace();
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
253 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
254
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
255 return ja;
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
256 }
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
257
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
258 /**
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
259 * creates an Annotation object with data from JSON.
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
260 *
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
261 * uses the specification from the annotator project: {@link https://github.com/okfn/annotator/wiki/Annotation-format}
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
262 *
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
263 * The username will be transformed to an URI if not given already as URI, if not it will set to the MPIWG namespace defined in
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
264 * de.mpiwg.itgroup.annotationManager.Constants.NS
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
265 *
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
266 * @param jo
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
267 * @return
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
268 * @throws JSONException
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
269 */
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
270 public Annotation createAnnotation(JSONObject jo, Representation entity) throws JSONException {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
271 return updateAnnotation(new Annotation(), jo, entity);
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
272 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
273
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
274 public Annotation updateAnnotation(Annotation annot, JSONObject jo, Representation entity) throws JSONException {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
275 // annotated uri
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
276 String url = annot.url;
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
277 if (jo.has("uri")) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
278 url = jo.getString("uri");
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
279 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
280 // annotation text
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
281 String text = annot.text;
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
282 if (jo.has("text")) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
283 text = jo.getString("text");
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
284 }
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
285 // check authentication
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
286 String authUser = checkAuthToken(entity);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
287 if (authUser == null) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
288 // try http auth
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
289 User httpUser = getHttpAuthUser(entity);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
290 if (httpUser == null) {
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
291 setStatus(Status.CLIENT_ERROR_FORBIDDEN);
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
292 return null;
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
293 }
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
294 authUser = httpUser.getIdentifier();
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
295 }
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
296 // username not required, if no username given authuser will be used
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
297 String username = null;
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
298 String userUri = annot.creator;
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
299 if (jo.has("user")) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
300 if (jo.get("user") instanceof String) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
301 // user is just a String
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
302 username = jo.getString("user");
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
303 // TODO: what if username and authUser are different?
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
304 } else {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
305 // user is an object
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
306 JSONObject user = jo.getJSONObject("user");
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
307 if (user.has("id")) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
308 username = user.getString("id");
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
309 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
310 if (user.has("uri")) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
311 userUri = user.getString("uri");
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
312 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
313 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
314 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
315 if (username == null) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
316 username = authUser;
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
317 }
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
318 // username should be a URI, if not it will set to the MPIWG namespace defined in
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
319 // de.mpiwg.itgroup.annotationManager.Constants.NS
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
320 if (userUri == null) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
321 if (username.startsWith("http")) {
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
322 userUri = username;
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
323 } else {
26
235b91ba8dff on the way to new annotations...
casties
parents: 24
diff changeset
324 userUri = NS.MPIWG_PERSONS_URL + username;
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
325 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
326 }
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
327 // TODO: should we overwrite the creator?
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
328
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
329 // create xpointer
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
330 String xpointer = annot.xpointer;
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
331 if (jo.has("ranges")) {
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
332 JSONObject ranges = jo.getJSONArray("ranges").getJSONObject(0);
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
333 String start = ranges.getString("start");
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
334 String end = ranges.getString("end");
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
335 String startOffset = ranges.getString("startOffset");
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
336 String endOffset = ranges.getString("endOffset");
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
337
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
338 try {
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
339 xpointer = url
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
340 + "#"
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
341 + URLEncoder.encode(String.format(
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
342 "xpointer(start-point(string-range(\"%s\",%s,1))/range-to(end-point(string-range(\"%s\",%s,1))))",
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
343 start, startOffset, end, endOffset), "utf-8");
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
344 } catch (UnsupportedEncodingException e) {
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
345 e.printStackTrace();
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
346 setStatus(Status.SERVER_ERROR_INTERNAL);
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
347 return null;
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
348 }
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
349 }
17
b0ef5c860464 updating and deleting annotations works now!
casties
parents: 15
diff changeset
350 return new Annotation(xpointer, userUri, annot.time, text, annot.type);
13
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
351 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
352
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
353 /**
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
354 * returns the logged in User.
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
355 *
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
356 * @param entity
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
357 * @return
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
358 */
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
359 protected User getHttpAuthUser(Representation entity) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
360 RestServer restServer = (RestServer) getApplication();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
361 if (!restServer.authenticate(getRequest(), getResponse())) {
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
362 // Not authenticated
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
363 return null;
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
364 }
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
365
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
366 ClientInfo ci = getRequest().getClientInfo();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
367 logger.debug(ci);
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
368 return getRequest().getClientInfo().getUser();
9393c9c9b916 saves annotations now!
casties
parents: 12
diff changeset
369
11
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
370 }
2f8c72ae4c43 working on create and read api for annotator.
casties
parents: 10
diff changeset
371
8
11baadcdd2c8 start of new Annotator API implementation.
casties
parents:
diff changeset
372 }