Project

General

Profile

« Previous | Next » 

Revision 9153

remove classes annotator classes that have moved to a different project under dataone's github.

View differences:

src/edu/ucsb/nceas/metacat/annotation/store/AnnotatorRestServlet.java
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author$'
7
 *     '$Date$'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.annotation.store;
24

  
25
import java.io.IOException;
26
import java.io.InputStream;
27

  
28
import javax.servlet.ServletConfig;
29
import javax.servlet.ServletException;
30
import javax.servlet.http.HttpServlet;
31
import javax.servlet.http.HttpServletRequest;
32
import javax.servlet.http.HttpServletResponse;
33

  
34
import net.minidev.json.JSONArray;
35
import net.minidev.json.JSONObject;
36
import net.minidev.json.JSONValue;
37

  
38
import org.apache.log4j.Logger;
39

  
40
/**
41
 * Metacat REST handler for Annotator storage API
42
 * http://docs.annotatorjs.org/en/v1.2.x/storage.html#core-storage-api 
43
 *  
44
 */
45
public class AnnotatorRestServlet extends HttpServlet {
46

  
47
    protected Logger logMetacat;
48
    
49
    private String getResource(HttpServletRequest request) {
50
    	// get the resource
51
        String resource = request.getPathInfo();
52
        resource = resource.substring(resource.indexOf("/") + 1);
53
        return resource;
54
    }
55
    
56
    /**
57
     * Initalize servlet by setting logger
58
     */
59
    @Override
60
    public void init(ServletConfig config) throws ServletException {
61
        logMetacat = Logger.getLogger(this.getClass());
62
        super.init(config);
63
    }
64

  
65
    /** Handle "GET" method requests from HTTP clients */
66
    @Override
67
    protected void doGet(HttpServletRequest request,
68
            HttpServletResponse response) throws ServletException, IOException {
69
        logMetacat.debug("HTTP Verb: GET");
70
        String resource = this.getResource(request);
71
        
72
        if (resource.startsWith("annotations/")) {
73
        	String id = request.getPathInfo().substring(request.getPathInfo().lastIndexOf("/") + 1);
74
        	AnnotatorStore as = new AnnotatorStore(request);
75
        	try {
76
				JSONObject annotation = as.read(id);
77
				annotation.writeJSONString(response.getWriter());
78
				return;
79
			} catch (Exception e) {
80
				throw new ServletException(e);
81
			}
82
        	
83
        }
84
        
85
        // handle listing them
86
        if (resource.startsWith("annotations")) {
87
        	AnnotatorStore as = new AnnotatorStore(request);
88
        	try {
89
				JSONArray annotations = as.index();
90
				annotations.writeJSONString(response.getWriter());
91
				return;
92
			} catch (Exception e) {
93
				throw new ServletException(e);
94
			}
95
        	
96
        }
97
        
98
        // handle searching them
99
        if (resource.startsWith("search")) {
100
        	String query = request.getQueryString();
101
        	AnnotatorStore as = new AnnotatorStore(request);
102
        	try {
103
				JSONObject results = as.search(query);
104
				results.writeJSONString(response.getWriter());
105
				return;
106
			} catch (Exception e) {
107
				e.printStackTrace();
108
				throw new ServletException(e);
109
			}
110
        	
111
        }
112
        
113
        
114
    }
115

  
116
    /** Handle "POST" method requests from HTTP clients */
117
    @Override
118
    protected void doPost(HttpServletRequest request,
119
            HttpServletResponse response) throws ServletException, IOException {
120
        logMetacat.debug("HTTP Verb: POST");
121

  
122
        String resource = this.getResource(request);
123
        if (resource.equals("annotations")) {
124
        	AnnotatorStore as = new AnnotatorStore(request);
125
        	try {
126
        		// get the annotation from the request
127
        		InputStream is = request.getInputStream();
128
    			JSONObject annotation = (JSONObject) JSONValue.parse(is);
129
    			
130
    			// create it on the node
131
				String id = as.create(annotation);
132
				
133
				// TODO: determine which is the correct approach for responding to CREATE
134
				
135
				// redirect to read
136
				response.setStatus(303);
137
				response.sendRedirect(request.getRequestURI() + "/" + id);
138
				
139
				// write it back in the response
140
				JSONObject result = as.read(id);
141
				result.writeJSONString(response.getWriter());
142
				
143
			} catch (Exception e) {
144
				throw new ServletException(e);
145
			}
146
        	
147
        }
148
    }
149

  
150
    /** Handle "DELETE" method requests from HTTP clients */
151
    @Override
152
    protected void doDelete(HttpServletRequest request,
153
            HttpServletResponse response) throws ServletException, IOException {
154
        logMetacat.debug("HTTP Verb: DELETE");
155
        
156
        
157
        String resource = this.getResource(request);
158
        if (resource.startsWith("annotations/")) {
159
        	String id = request.getPathInfo().substring(request.getPathInfo().lastIndexOf("/") + 1);
160
        	AnnotatorStore as = new AnnotatorStore(request);
161
        	try {
162
        		// delete the annotation
163
        		as.delete(id);
164
        		
165
        		// say no content
166
        		response.setContentLength(0);
167
				response.setStatus(204);
168
				
169
			} catch (Exception e) {
170
				throw new ServletException(e);
171
			}
172
        	
173
        }
174
        
175
    }
176

  
177
    /** Handle "PUT" method requests from HTTP clients */
178
    @Override
179
    protected void doPut(HttpServletRequest request,
180
            HttpServletResponse response) throws ServletException, IOException {
181
        logMetacat.debug("HTTP Verb: PUT");
182
    }
183

  
184
    /** Handle "HEAD" method requests from HTTP clients */
185
    @Override
186
    protected void doHead(HttpServletRequest request,
187
            HttpServletResponse response) throws ServletException, IOException {
188
        logMetacat.debug("HTTP Verb: HEAD");
189
    }
190
}
191 0

  
src/edu/ucsb/nceas/metacat/annotation/store/AnnotatorStore.java
1
/**
2
 * 
3
 */
4
package edu.ucsb.nceas.metacat.annotation.store;
5

  
6
import java.io.ByteArrayInputStream;
7
import java.io.InputStream;
8
import java.math.BigInteger;
9
import java.nio.charset.Charset;
10
import java.util.ArrayList;
11
import java.util.Calendar;
12
import java.util.Collection;
13
import java.util.Date;
14
import java.util.List;
15

  
16
import javax.servlet.http.HttpServletRequest;
17

  
18
import org.apache.commons.collections.CollectionUtils;
19
import org.apache.commons.collections.Predicate;
20
import org.apache.commons.collections.PredicateUtils;
21
import org.apache.commons.logging.Log;
22
import org.apache.commons.logging.LogFactory;
23
import org.apache.http.NameValuePair;
24
import org.apache.http.client.utils.URLEncodedUtils;
25
import org.dataone.client.auth.CertificateManager;
26
import org.dataone.portal.TokenGenerator;
27
import org.dataone.service.exceptions.InvalidToken;
28
import org.dataone.service.types.v1.AccessPolicy;
29
import org.dataone.service.types.v1.AccessRule;
30
import org.dataone.service.types.v1.Checksum;
31
import org.dataone.service.types.v1.Identifier;
32
import org.dataone.service.types.v1.NodeReference;
33
import org.dataone.service.types.v1.ObjectFormatIdentifier;
34
import org.dataone.service.types.v1.ObjectInfo;
35
import org.dataone.service.types.v1.ObjectList;
36
import org.dataone.service.types.v1.Permission;
37
import org.dataone.service.types.v1.Session;
38
import org.dataone.service.types.v1.Subject;
39
import org.dataone.service.types.v1.util.ChecksumUtil;
40
import org.dataone.service.types.v2.SystemMetadata;
41
import org.dataone.service.util.Constants;
42
import org.dataone.service.util.DateTimeMarshaller;
43

  
44

  
45
import edu.ucsb.nceas.metacat.MetaCatServlet;
46
import edu.ucsb.nceas.metacat.dataone.MNodeService;
47
import net.minidev.json.JSONArray;
48
import net.minidev.json.JSONObject;
49
import net.minidev.json.JSONValue;
50

  
51
/**
52
 * @author leinfelder
53
 *
54
 */
55
public class AnnotatorStore {
56

  
57
    public static Log logMetacat = LogFactory.getLog(AnnotatorStore.class);
58

  
59
    public static final String ANNOTATION_FORMAT_ID = "http://docs.annotatorjs.org/en/v1.2.x/annotation-format.html";
60
	
61
    private HttpServletRequest request;
62
	private Session session;
63
	
64
	public AnnotatorStore(HttpServletRequest request) {
65
		
66
		this.request = request;
67
		
68
		try {
69
			session = CertificateManager.getInstance().getSession(request);
70
		} catch (InvalidToken e) {
71
			logMetacat.warn(e.getMessage(), e);
72
		}
73
		
74
		// try getting it from the token
75
		if (session == null) {
76
			String token = request.getHeader("x-annotator-auth-token");
77
			session = TokenGenerator.getSession(token);
78
		}
79
		
80
	}
81
	
82
	/**
83
	 * Generate minimal systemmetadata for new/updated annotation objects
84
	 * @param annotation
85
	 * @return
86
	 * @throws Exception
87
	 */
88
	private SystemMetadata computeSystemMetadata(JSONObject annotation) throws Exception {
89
		SystemMetadata sysmeta = new SystemMetadata();
90
		
91
		ObjectFormatIdentifier formatId = new ObjectFormatIdentifier();
92
		formatId.setValue(ANNOTATION_FORMAT_ID);
93
		sysmeta.setFormatId(formatId);
94
		
95
		BigInteger size = BigInteger.valueOf(annotation.toJSONString().getBytes(MetaCatServlet.DEFAULT_ENCODING).length);
96
		sysmeta.setSize(size);
97
		
98
		Checksum checksum = ChecksumUtil.checksum(annotation.toJSONString().getBytes(MetaCatServlet.DEFAULT_ENCODING), "MD5");
99
		sysmeta.setChecksum(checksum);
100
		
101
		Subject rightsHolder = session.getSubject();
102
		sysmeta.setRightsHolder(rightsHolder);
103
		sysmeta.setSubmitter(rightsHolder);
104

  
105
		NodeReference authoritativeMemberNode = MNodeService.getInstance(request).getCapabilities().getIdentifier();
106
		sysmeta.setAuthoritativeMemberNode(authoritativeMemberNode );
107
		sysmeta.setOriginMemberNode(authoritativeMemberNode);
108
		
109
		sysmeta.setDateSysMetadataModified(DateTimeMarshaller.deserializeDateToUTC(annotation.get("updated").toString()));
110
		sysmeta.setDateUploaded(DateTimeMarshaller.deserializeDateToUTC(annotation.get("created").toString()));		
111
	
112
		// add access access rules for read
113
		AccessPolicy accessPolicy = new AccessPolicy();
114
		JSONObject permissions =  (JSONObject) annotation.get("permissions");
115
		JSONArray readList = (JSONArray) permissions.get("read");
116
		for (Object read: readList) {
117
			AccessRule accessRule = new AccessRule();
118
			Subject user = new Subject();
119
			
120
			String username = read.toString();
121
			if (username.equals("group:__world__")) {
122
				user.setValue(Constants.SUBJECT_PUBLIC);
123
			}
124
			accessRule.addSubject(user);
125
			accessRule.addPermission(Permission.READ);
126
			accessPolicy.addAllow(accessRule);
127
			
128
		}
129
		sysmeta.setAccessPolicy(accessPolicy);
130

  
131
		return sysmeta;
132
	}
133
	
134
	/**
135
	 * Create a new annotation from given object
136
	 * @param annotation
137
	 * @return the generated identifier for the annotation
138
	 * @throws Exception
139
	 */
140
	public String create(JSONObject annotation) throws Exception {
141
		
142
		// use the dataone API to create an object for the annotation
143
		
144
		// create identifiers for the object
145
		Identifier pid = MNodeService.getInstance(request).generateIdentifier(session, "UUID", "annotation");
146
		Identifier sid = MNodeService.getInstance(request).generateIdentifier(session, "UUID", "annotation");
147
		
148
		// add properties to the annotation
149
		// TODO: use SID for the identifier when implemented
150
		annotation.put("id", pid.getValue());
151
		annotation.put("user", session.getSubject().getValue());
152
		Date now = Calendar.getInstance().getTime();
153
		annotation.put("created", DateTimeMarshaller.serializeDateToUTC(now));
154
		annotation.put("updated", DateTimeMarshaller.serializeDateToUTC(now));
155

  
156
		// generate sys meta
157
		SystemMetadata sysmeta = computeSystemMetadata(annotation);
158
		sysmeta.setIdentifier(pid);
159
		sysmeta.setSeriesId(sid);
160
		
161
		// create it on the node
162
		InputStream object = new ByteArrayInputStream(annotation.toJSONString().getBytes(MetaCatServlet.DEFAULT_ENCODING));
163
		MNodeService.getInstance(request).create(session, pid, object, sysmeta);
164
		
165
		return pid.getValue();
166
	}
167

  
168
	/**
169
	 * Read the annotation for given id
170
	 * @param id
171
	 * @return
172
	 * @throws Exception
173
	 */
174
	public JSONObject read(String id) throws Exception {
175
		// read the annotation out as JSON object
176
		Identifier sid = new Identifier();
177
		sid.setValue(id);
178
		InputStream object = MNodeService.getInstance(request).get(session, sid);
179
		JSONObject annotation = (JSONObject) JSONValue.parse(object);
180
		return annotation;
181
	}
182

  
183
	/**
184
	 * TODO: implement when series ID is supported
185
	 * @param id
186
	 * @param partialAnnotation
187
	 * @return
188
	 */
189
	public JSONObject update(String id, JSONObject partialAnnotation) {
190
		// TODO Auto-generated method stub
191
		return null;
192
	}
193

  
194
	/**
195
	 * TODO: allow full delete?
196
	 * Remove the annotation from the store
197
	 * @param id
198
	 * @throws Exception
199
	 */
200
	public void delete(String id) throws Exception {
201
		// read the annotation out as JSON object
202
		Identifier sid = new Identifier();
203
		sid.setValue(id);
204
		
205
		//MNodeService.getInstance(request).delete(session, sid);
206
		MNodeService.getInstance(request).archive(session, sid);
207

  
208
	}
209

  
210
	/**
211
	 * Query annotation store using given query expression
212
	 * @param query
213
	 * @return result listing the total matches and each annotation as a "row"
214
	 * @throws Exception
215
	 */
216
	public JSONObject search(String query) throws Exception {
217
		
218
		JSONObject results = new JSONObject();
219
		
220
		// TODO: better search algorithm!
221
		JSONArray annotations = this.index();
222
		
223
		Collection<Predicate> predicates = new ArrayList<Predicate>();
224
		List<NameValuePair> criteria = URLEncodedUtils.parse(query, Charset.forName(MetaCatServlet.DEFAULT_ENCODING));
225
		for (NameValuePair pair: criteria) {
226
			if (pair.getName().equals("limit") || pair.getName().equals("offset")) {
227
				continue;
228
			}
229
			// otherwise add the criteria
230
			predicates.add(new AnnotationPredicate(pair.getName(), pair.getValue()));
231
			
232
		}
233
		Predicate allPredicate = PredicateUtils.allPredicate(predicates);
234
		CollectionUtils.filter(annotations, allPredicate);
235
		
236
		results.put("total", annotations.size());
237
		results.put("rows", annotations);
238
		return results ;
239
	}
240

  
241
	/**
242
	 * Show the API version information for this store
243
	 * @return
244
	 */
245
	public JSONObject root() {
246
		JSONObject versionInfo = new JSONObject();
247
		versionInfo.put("name", "Metacat Annotator Store API");
248
		versionInfo.put("version", "1.2.9");
249
		return versionInfo ;
250
	}
251

  
252
	/**
253
	 * List all the annotations in the store
254
	 * @return
255
	 * @throws Exception
256
	 */
257
	public JSONArray index() throws Exception {
258
		
259
		JSONArray annotations = new JSONArray();
260
		ObjectFormatIdentifier objectFormatId = new ObjectFormatIdentifier();
261
		objectFormatId.setValue(ANNOTATION_FORMAT_ID);
262
		Integer start = 0;
263
		Integer count = 1000;
264
		ObjectList objects = MNodeService.getInstance(request).listObjects(session, null, null, objectFormatId, null, true, start, count);
265
		for (ObjectInfo info: objects.getObjectInfoList()) {
266
			Identifier pid = info.getIdentifier();
267
			SystemMetadata sysMeta = MNodeService.getInstance(request).getSystemMetadata(session, pid);
268
			// remember we don't have true delete yet
269
			if ( (sysMeta.getArchived() != null && sysMeta.getArchived().booleanValue()) || sysMeta.getObsoletedBy() != null) {
270
				continue;
271
			}
272
			JSONObject annotation = this.read(pid.getValue());
273
			annotations.add(annotation);
274
		}
275

  
276
		return annotations ;
277
	}
278

  
279
}
280

  
281
class AnnotationPredicate implements Predicate {
282

  
283
	private String name;
284
	private String value;
285
	
286
	public AnnotationPredicate(String name, String value) {
287
		this.name = name;
288
		this.value = value;
289
	}
290
	
291
	@Override
292
	public boolean evaluate(Object obj) {
293
		JSONObject annotation = (JSONObject) obj;
294
		// simple string equals for now
295
		String actualValue = (String) annotation.get(name);
296
		if (actualValue == null) {
297
			return false;
298
		}
299
		return actualValue.equals(value);
300
	}
301
		
302
}
303

  
304 0

  

Also available in: Unified diff