annotate src/main/java/de/mpiwg/itgroup/annotations/restlet/AnnotatorResourceImpl.java @ 3:47b53ae385d1

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