Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2011 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: leinfelder $'
7
 *     '$Date: 2011-06-30 17:24:29 -0700 (Thu, 30 Jun 2011) $'
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.restservice;
24

    
25
import java.io.ByteArrayInputStream;
26
import java.io.File;
27
import java.io.FileInputStream;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.io.UnsupportedEncodingException;
32
import java.text.DateFormat;
33
import java.text.ParseException;
34
import java.text.SimpleDateFormat;
35
import java.util.Date;
36
import java.util.Enumeration;
37
import java.util.Map;
38

    
39
import javax.servlet.ServletContext;
40
import javax.servlet.http.HttpServletRequest;
41
import javax.servlet.http.HttpServletResponse;
42

    
43
import org.apache.commons.fileupload.FileUploadException;
44
import org.apache.commons.io.IOUtils;
45
import org.apache.log4j.Logger;
46
import org.dataone.client.ObjectFormatCache;
47
import org.dataone.service.exceptions.BaseException;
48
import org.dataone.service.exceptions.IdentifierNotUnique;
49
import org.dataone.service.exceptions.InsufficientResources;
50
import org.dataone.service.exceptions.InvalidRequest;
51
import org.dataone.service.exceptions.InvalidSystemMetadata;
52
import org.dataone.service.exceptions.InvalidToken;
53
import org.dataone.service.exceptions.NotAuthorized;
54
import org.dataone.service.exceptions.NotFound;
55
import org.dataone.service.exceptions.NotImplemented;
56
import org.dataone.service.exceptions.ServiceFailure;
57
import org.dataone.service.exceptions.SynchronizationFailed;
58
import org.dataone.service.exceptions.UnsupportedType;
59
import org.dataone.service.types.AccessPolicy;
60
import org.dataone.service.types.Checksum;
61
import org.dataone.service.types.DescribeResponse;
62
import org.dataone.service.types.Event;
63
import org.dataone.service.types.Identifier;
64
import org.dataone.service.types.Log;
65
import org.dataone.service.types.MonitorList;
66
import org.dataone.service.types.Node;
67
import org.dataone.service.types.NodeList;
68
import org.dataone.service.types.NodeReference;
69
import org.dataone.service.types.ObjectFormat;
70
import org.dataone.service.types.ObjectList;
71
import org.dataone.service.types.Permission;
72
import org.dataone.service.types.Subject;
73
import org.dataone.service.types.SystemMetadata;
74
import org.jibx.runtime.JiBXException;
75

    
76
import edu.ucsb.nceas.metacat.dataone.MNodeService;
77

    
78
/**
79
 * MN REST service implementation handler
80
 * 
81
 * ******************
82
 * MNCore -- DONE
83
 * 		ping() - GET /d1/mn/monitor/ping
84
 * 		log() - GET /d1/mn/log
85
 * 		**getObjectStatistics() - GET /d1/mn/monitor/object
86
 * 		getOperationsStatistics - GET /d1/mn/monitor/event
87
 * 		**getStatus - GET /d1/mn/monitor/status
88
 * 		getCapabilities() - GET /d1/mn/ and /d1/mn/node
89
 * 	
90
 * 	MNRead -- DONE
91
 * 		get() - GET /d1/mn/object/PID
92
 * 		getSystemMetadata() - GET /d1/mn/meta/PID
93
 * 		describe() - HEAD /d1/mn/object/PID
94
 * 		getChecksum() - GET /d1/mn/checksum/PID
95
 * 		listObjects() - GET /d1/mn/object
96
 * 		synchronizationFailed() - POST /d1/mn/error
97
 * 	
98
 * 	MNAuthorization -- DONE
99
 * 		isAuthorized() - GET /d1/mn/isAuthorized/PID
100
 * 		setAccessPolicy() - PUT /d1/mn/accessRules/PID
101
 * 		
102
 * 	MNStorage
103
 * 		create() - POST /d1/mn/object/PID
104
 * 		update() - PUT /d1/mn/object/PID
105
 * 		delete() - DELETE /d1/mn/object/PID
106
 * 	
107
 * 	MNReplication
108
 * 		replicate() - POST /d1/mn/replicate
109
 * 
110
 * ******************
111
 * @author leinfelder
112
 *
113
 */
114
public class MNResourceHandler extends D1ResourceHandler{
115

    
116
    // MN-specific API Resources
117
    protected static final String RESOURCE_MONITOR = "monitor";
118
    protected static final String RESOURCE_REPLICATE = "replicate";
119
    protected static final String RESOURCE_NODE = "node";
120
    protected static final String RESOURCE_ERROR = "error";
121

    
122

    
123
    /**
124
     * Initializes new instance by setting servlet context,request and response
125
     * */
126
    public MNResourceHandler(ServletContext servletContext,
127
            HttpServletRequest request, HttpServletResponse response) {
128
    	super(servletContext, request, response);
129
        logMetacat = Logger.getLogger(MNResourceHandler.class);
130
    }
131

    
132
    /**
133
     * This function is called from REST API servlet and handles each request to the servlet 
134
     * 
135
     * @param httpVerb (GET, POST, PUT or DELETE)
136
     */
137
    @Override
138
    public void handle(byte httpVerb) {
139
    	// prepare the handler
140
    	super.handle(httpVerb);
141
    	
142
        try {
143
            String resourcePrefix = RESOURCE_BASE_URL + "/mn/";
144
        	String resource = request.getServletPath();
145
            
146
            if (resource.endsWith(resourcePrefix)) {
147
                resource = RESOURCE_NODE;
148
            }
149
            else {
150
            	// remove prefix
151
                resource = resource.substring(resource.indexOf(resourcePrefix) + resourcePrefix.length());
152
                resource = resource.trim();
153
            }
154
                        
155
            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
156
            logMetacat.debug("resource: '" + resource + "'");
157
            boolean status = false;
158
            
159
            if (resource != null) {
160

    
161
                if (resource.equals(RESOURCE_NODE)) {
162
                    // node response
163
                    node();
164
                    status = true;
165
                    
166
                } else if (resource.equals(RESOURCE_ACCESS_RULES)) {
167
                    if (httpVerb == POST) {
168
	                	// set the access rules
169
	                    setAccess();
170
	                    status = true;
171
	                    logMetacat.debug("done setting access");
172
                    }
173
                } else if (resource.equals(RESOURCE_IS_AUTHORIZED)) {
174
                    if (httpVerb == GET) {
175
	                	// check the access rules
176
                    	String objectId = request.getPathInfo();
177
                        if (objectId != null && objectId.length() > 1) {
178
                            objectId = request.getPathInfo().substring(1);
179
                        }
180
	                    isAuthorized(objectId);
181
	                    status = true;
182
	                    logMetacat.debug("done getting access");
183
                    }
184
                } else if (resource.equals(RESOURCE_META)) {
185
                    logMetacat.debug("Using resource 'meta'");
186
                    String objectId = request.getPathInfo();
187
                    if (objectId != null && objectId.length() > 1) {
188
                        objectId = request.getPathInfo().substring(1);
189
                    }
190
                    
191
                    // get
192
                    if (httpVerb == GET) {
193
                        getSystemMetadataObject(objectId);
194
                        status = true;
195
                    }
196
                    
197
                } else if (resource.equals(RESOURCE_OBJECTS)) {
198
                    logMetacat.debug("Using resource 'object'");
199

    
200
                    String objectId = request.getPathInfo();
201
                    if (objectId != null && objectId.length() > 1) {
202
                        objectId = request.getPathInfo().substring(1);
203
                    } else {
204
                        objectId = null;
205
                    }
206
                    
207
                    logMetacat.debug("objectId: " + objectId);
208
                    logMetacat.debug("verb:" + httpVerb);
209

    
210
                    if (httpVerb == GET) {
211
                        getObject(objectId);
212
                        status = true;
213
                    } else if (httpVerb == POST) {
214
                        putObject(objectId, FUNCTION_NAME_INSERT);
215
                        status = true;
216
                    } else if (httpVerb == PUT) {
217
                        putObject(objectId, FUNCTION_NAME_UPDATE);
218
                        status = true;
219
                    } else if (httpVerb == DELETE) {
220
                        deleteObject(objectId);
221
                        status = true;
222
                    } else if (httpVerb == HEAD) {
223
                        describeObject(objectId);
224
                        status = true;
225
                    }
226
                  
227
                } else if (resource.equals(RESOURCE_LOG)) {
228
                    logMetacat.debug("Using resource 'log'");
229
                    // handle log events
230
                    if (httpVerb == GET) {
231
                        getLog();
232
                        status = true;
233
                    }
234
                } else if (resource.equals(RESOURCE_CHECKSUM)) {
235
                    logMetacat.debug("Using resource 'checksum'");
236
                    // handle checksum requests
237
                    if (httpVerb == GET) {
238
                        checksum();
239
                        status = true;
240
                    }
241
                } else if (resource.startsWith(RESOURCE_MONITOR)) {
242
                    // there are various parts to monitoring
243
                    if (httpVerb == GET) {
244
                    	// health monitoring calls
245
                        status = monitor();
246
                    }
247
                } else if (resource.equals(RESOURCE_REPLICATE)) {
248
                	if (httpVerb == POST) {
249
	                    logMetacat.debug("processing replicate request");
250
	                    replicate();
251
	                    status = true;
252
                	}
253
                } else if (resource.equals(RESOURCE_ERROR)) {
254
	                // sync error
255
	                if (httpVerb == POST) {
256
	                    syncError();
257
	                    status = true;
258
	                }
259
                }
260
                
261
                if (!status) {
262
                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
263
                }
264
            } else {
265
            	throw new InvalidRequest("0000", "No resource matched for " + resource);
266
            }
267
        } catch (BaseException be) {
268
        	// report Exceptions as clearly as possible
269
        	OutputStream out = null;
270
			try {
271
				out = response.getOutputStream();
272
			} catch (IOException e) {
273
				logMetacat.error("Could not get output stream from response", e);
274
			}
275
            serializeException(be, out);
276
        } catch (Exception e) {
277
            // report Exceptions as clearly and generically as possible
278
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
279
        	OutputStream out = null;
280
			try {
281
				out = response.getOutputStream();
282
			} catch (IOException ioe) {
283
				logMetacat.error("Could not get output stream from response", ioe);
284
			}
285
			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
286
            serializeException(se, out);
287
        }
288
    }
289
    
290
    /**
291
     * Checks the access policy
292
     * @param id
293
     * @return
294
     * @throws ServiceFailure
295
     * @throws InvalidToken
296
     * @throws NotFound
297
     * @throws NotAuthorized
298
     * @throws NotImplemented
299
     * @throws InvalidRequest
300
     */
301
    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
302
		Identifier pid = new Identifier();
303
		pid.setValue(id);
304
		Permission permission = null;
305
		try {
306
			String perm = params.get("permission")[0];
307
			permission = Permission.valueOf(perm);
308
		} catch (Exception e) {
309
			logMetacat.warn("No permission specified");
310
		}
311
		boolean result = MNodeService.getInstance().isAuthorized(session, pid, permission);
312
		response.setStatus(200);
313
		response.setContentType("text/xml");
314
		return result;
315
    }
316
    
317
    /**
318
     * Processes failed synchronization message
319
     * @throws NotImplemented
320
     * @throws ServiceFailure
321
     * @throws NotAuthorized
322
     * @throws InvalidRequest
323
     * @throws UnsupportedEncodingException
324
     * @throws JiBXException
325
     */
326
    private void syncError() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, UnsupportedEncodingException, JiBXException {
327
    	SynchronizationFailed syncFailed = null;
328
    	if (params.containsKey("message")) {
329
            String message = params.get("message")[0];
330
            syncFailed = (SynchronizationFailed) deserializeServiceType(SynchronizationFailed.class, new ByteArrayInputStream(message.getBytes("UTF-8")));
331
        }
332
		MNodeService.getInstance().synchronizationFailed(session, syncFailed);
333
    }
334
    
335
    /**
336
     * Handles the monitoring resources
337
     * @return
338
     * @throws NotFound
339
     * @throws ParseException
340
     * @throws NotImplemented
341
     * @throws ServiceFailure
342
     * @throws NotAuthorized
343
     * @throws InvalidRequest
344
     * @throws InsufficientResources
345
     * @throws UnsupportedType
346
     * @throws IOException
347
     * @throws JiBXException
348
     */
349
    private boolean monitor() throws NotFound, ParseException, NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, InsufficientResources, UnsupportedType, IOException, JiBXException {
350
    	logMetacat.debug("processing monitor request");
351
        String pathInfo = request.getPathInfo();
352
        
353
        logMetacat.debug("verb is GET");
354
        logMetacat.debug("pathInfo is " + pathInfo);
355
        pathInfo = pathInfo.substring(1);
356
        
357
        if (pathInfo.toLowerCase().equals("ping")) {
358
            logMetacat.debug("processing ping request");
359
            boolean result = MNodeService.getInstance().ping();
360
            return result;
361
            
362
        } else if (pathInfo.toLowerCase().equals("status")) {
363
            logMetacat.debug("processing status request");
364
            // TODO: implement in MNCore
365
            //MNodeService.getInstance().getStatus();
366
            return false;
367
            
368
        } else if (pathInfo.toLowerCase().equals("object")) {
369
            logMetacat.debug("processing object request");
370
            Identifier pid = null;
371
            ObjectFormat format = null;
372
            if (params.containsKey("format")) {
373
                String f = params.get("format")[0];
374
                format = ObjectFormatCache.getInstance().getFormat(f);
375
            }
376
            if (params.containsKey("pid")) {
377
                String id = params.get("pid")[0];
378
                pid = new Identifier();
379
                pid.setValue(id);
380
            }
381
            
382
            // TODO: implement in MNCore
383
            //ObjectStatistics objectStats = MNodeService.getInstance().getObjectStatistics(format, pid);
384
            return false;
385
            
386
        } else if (pathInfo.toLowerCase().equals("event")) {
387
            logMetacat.debug("processing event request");
388
            ObjectFormat format = null;
389
            Integer period = null;
390
            String requestor = null;
391
            Subject subject = null;
392
            String eventName = null;
393
            Event event = null;
394

    
395
            if (params.containsKey("format")) {
396
                String f = params.get("format")[0];
397
                format = ObjectFormatCache.getInstance().getFormat(f);
398
            }
399
            if (params.containsKey("period")) {
400
                String t = params.get("period")[0];
401
                period = Integer.valueOf(t);
402
            }
403
            if (params.containsKey("requestor")) {
404
            	requestor = params.get("requestor")[0];
405
            	subject = new Subject();
406
            	subject.setValue(requestor);
407
            }
408
            if (params.containsKey("event")) {
409
            	eventName = params.get("event")[0];
410
                event = Event.valueOf(eventName);
411
            }
412
            
413
            MonitorList monitorList = MNodeService.getInstance().getOperationStatistics(session, period, subject, event, format);
414
            
415
            OutputStream out = response.getOutputStream();
416
            response.setStatus(200);
417
            response.setContentType("text/xml");
418
            
419
            serializeServiceType(MonitorList.class, monitorList, out);
420
            
421
            return true;
422
            
423
        }
424
        
425
        return false;
426
    }
427
    
428
    /**
429
     * Calculate the checksum 
430
     * @throws NotImplemented
431
     * @throws JiBXException
432
     * @throws IOException
433
     * @throws InvalidToken
434
     * @throws ServiceFailure
435
     * @throws NotAuthorized
436
     * @throws NotFound
437
     * @throws InvalidRequest
438
     */
439
    private void checksum() throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
440
    	String checksumAlgorithm = "MD5";
441
        String guid = request.getPathInfo();
442
        if (guid != null && guid.length() > 1) {
443
            guid = request.getPathInfo().substring(1); // trim the slash
444
        }
445
        Identifier guidid = new Identifier();
446
        guidid.setValue(guid);
447
        try {
448
            checksumAlgorithm = params.get("checksumAlgorithm")[0];
449
        } catch(Exception e) {
450
            //do nothing.  default to MD5
451
        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
452
        }
453
        logMetacat.debug("getting checksum for object " + guid + " with algorithm " + checksumAlgorithm);
454
        
455
        Checksum c = MNodeService.getInstance().getChecksum(session, guidid, checksumAlgorithm);
456
        logMetacat.debug("got checksum " + c.getValue());
457
        response.setStatus(200);
458
        logMetacat.debug("serializing response");
459
        serializeServiceType(Checksum.class, c, response.getOutputStream());
460
        logMetacat.debug("done serializing response.");
461
        
462
    }
463
    
464
	/**
465
     * handle the replicate action for MN
466
	 * @throws JiBXException 
467
	 * @throws FileUploadException 
468
	 * @throws IOException 
469
	 * @throws InvalidRequest 
470
	 * @throws ServiceFailure 
471
	 * @throws UnsupportedType 
472
	 * @throws InsufficientResources 
473
	 * @throws NotAuthorized 
474
	 * @throws NotImplemented 
475
     */
476
    private void replicate() throws ServiceFailure, InvalidRequest, IOException, FileUploadException, JiBXException, NotImplemented, NotAuthorized, InsufficientResources, UnsupportedType {
477

    
478
        logMetacat.debug("in POST replicate()");
479
        
480
        //parse the systemMetadata
481
        SystemMetadata sysmeta = collectSystemMetadata();
482
        
483
        String sn = multipartparams.get("sourceNode").get(0);
484
        logMetacat.debug("sourceNode: " + sn);
485
        NodeReference sourceNode = (NodeReference) deserializeServiceType(NodeReference.class, new ByteArrayInputStream(sn.getBytes("UTF-8")));
486
        
487
        MNodeService.getInstance().replicate(session, sysmeta, sourceNode);
488

    
489
        response.setStatus(200);
490

    
491
    }
492
    
493
    /**
494
     * Get the Node information
495
     * 
496
     * @throws JiBXException
497
     * @throws IOException
498
     * @throws InvalidRequest 
499
     * @throws ServiceFailure 
500
     * @throws NotAuthorized 
501
     * @throws NotImplemented 
502
     */
503
    private void node() 
504
        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
505
        
506
        Node n = MNodeService.getInstance().getCapabilities();
507
        
508
        NodeList nl = new NodeList();
509
        nl.addNode(n);
510
        
511
        response.setContentType("text/xml");
512
        response.setStatus(200);
513
        serializeServiceType(NodeList.class, nl, response.getOutputStream());
514
        
515
    }
516
    
517
    /**
518
     * MN_crud.describe()
519
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
520
     * @param guid
521
     * @throws InvalidRequest 
522
     * @throws NotImplemented 
523
     * @throws NotFound 
524
     * @throws NotAuthorized 
525
     * @throws ServiceFailure 
526
     * @throws InvalidToken 
527
     */
528
    private void describeObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
529
    {
530
        response.setStatus(200);
531
        response.setContentType("text/xml");
532
        
533
        Identifier id = new Identifier();
534
        id.setValue(guid);
535

    
536
        DescribeResponse dr = MNodeService.getInstance().describe(session, id);
537
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SZ");
538
        response.addHeader("guid", guid);
539
        response.addHeader("checksum", dr.getDataONE_Checksum().getValue());
540
        response.addHeader("checksum_algorithm", dr.getDataONE_Checksum().getAlgorithm().name());
541
        response.addHeader("content_length", dr.getContent_Length() + "");
542
        response.addHeader("last_modified", dateFormat.format(dr.getLast_Modified()));
543
        response.addHeader("format", dr.getDataONE_ObjectFormat().toString());
544
       
545
    }
546
    
547
    /**
548
     * get the logs based on passed params.  Available 
549
     * See http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
550
     * for more info
551
     * @throws NotImplemented 
552
     * @throws InvalidRequest 
553
     * @throws NotAuthorized 
554
     * @throws ServiceFailure 
555
     * @throws InvalidToken 
556
     * @throws IOException 
557
     * @throws JiBXException 
558
     */
559
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
560
    {
561
            
562
        Date fromDate = null;
563
        Date toDate = null;
564
        Event event = null;
565
        Integer start = null;
566
        Integer count = null;
567
        
568
        try {
569
        	String fromDateS = params.get("fromDate")[0];
570
            logMetacat.debug("param fromDateS: " + fromDateS);
571
            fromDate = parseDateAndConvertToGMT(fromDateS);
572
        } catch (Exception e) {
573
        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
574
        }
575
        try {
576
        	String toDateS = params.get("toDate")[0];
577
            logMetacat.debug("param toDateS: " + toDateS);
578
            toDate = parseDateAndConvertToGMT(toDateS);
579
        } catch (Exception e) {
580
        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
581
		}
582
        try {
583
        	String eventS = params.get("event")[0];
584
            event = Event.convert(eventS);
585
        } catch (Exception e) {
586
        	logMetacat.warn("Could not parse event: " + e.getMessage());
587
		}
588
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
589
        
590
        try {
591
        	start =  Integer.parseInt(params.get("start")[0]);
592
        } catch (Exception e) {
593
			logMetacat.warn("Could not parse start: " + e.getMessage());
594
		}
595
        try {
596
        	count =  Integer.parseInt(params.get("count")[0]);
597
        } catch (Exception e) {
598
			logMetacat.warn("Could not parse count: " + e.getMessage());
599
		}
600
        
601
        logMetacat.debug("calling getLogRecords");
602
        Log log = MNodeService.getInstance().getLogRecords(session, fromDate, toDate, event, start, count);
603
        
604
        OutputStream out = response.getOutputStream();
605
        response.setStatus(200);
606
        response.setContentType("text/xml");
607
        
608
        serializeServiceType(Log.class, log, out);
609
        
610
    }
611
    
612
    /**
613
     * Implements REST version of DataONE CRUD API --> get
614
     * @param guid ID of data object to be read
615
     * @throws NotImplemented 
616
     * @throws InvalidRequest 
617
     * @throws NotFound 
618
     * @throws NotAuthorized 
619
     * @throws ServiceFailure 
620
     * @throws InvalidToken 
621
     * @throws IOException 
622
     * @throws JiBXException 
623
     */
624
    protected void getObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
625
        OutputStream out = null;
626
        
627
        if (guid != null) { //get a specific document                
628
            Identifier id = new Identifier();
629
            id.setValue(guid);
630
                
631
            SystemMetadata sm = MNodeService.getInstance().getSystemMetadata(session, id);
632
            
633
            //set the content type
634
            if (sm.getObjectFormat().getFmtid().getValue().trim().equals(
635
            		ObjectFormatCache.getInstance().getFormat("text/csv").getFmtid().getValue()))
636
            {
637
                response.setContentType("text/csv");
638
                response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".csv");
639
            }
640
            else if (sm.getObjectFormat().getFmtid().getValue().trim().equals(
641
            		ObjectFormatCache.getInstance().getFormat("text/plain").getFmtid().getValue()))
642
            {
643
                response.setContentType("text/plain");
644
                response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".txt");
645
            } 
646
            else if (sm.getObjectFormat().getFmtid().getValue().trim().equals(
647
            		ObjectFormatCache.getInstance().getFormat("application/octet-stream").getFmtid().getValue()))
648
            {
649
                response.setContentType("application/octet-stream");
650
            }
651
            else
652
            {
653
                response.setContentType("text/xml");
654
                response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".xml");
655
            }
656
            
657
            InputStream data = MNodeService.getInstance().get(session, id);
658

    
659
            out = response.getOutputStream();  
660
            IOUtils.copyLarge(data, out);
661
            
662
        }
663
        else
664
        { //call listObjects with specified params
665
            Date startTime = null;
666
            Date endTime = null;
667
            ObjectFormat objectFormat = null;
668
            boolean replicaStatus = false;
669
            int start = 0;
670
            //TODO: make the max count into a const
671
            int count = 1000;
672
            Enumeration paramlist = request.getParameterNames();
673
            while (paramlist.hasMoreElements()) 
674
            { //parse the params and make the crud call
675
                String name = (String) paramlist.nextElement();
676
                String[] value = (String[])request.getParameterValues(name);
677

    
678
                if (name.equals("startTime") && value != null)
679
                {
680
                    try
681
                    {
682
                      //startTime = dateFormat.parse(value[0]);
683
                        startTime = parseDateAndConvertToGMT(value[0]);
684
                    }
685
                    catch(Exception e)
686
                    {  //if we can't parse it, just don't use the startTime param
687
                        logMetacat.warn("Could not parse startTime: " + value[0]);
688
                        startTime = null;
689
                    }
690
                }
691
                else if(name.equals("endTime") && value != null)
692
                {
693
                    try
694
                    {
695
                      //endTime = dateFormat.parse(value[0]);
696
                        endTime = parseDateAndConvertToGMT(value[0]);
697
                    }
698
                    catch(Exception e)
699
                    {  //if we can't parse it, just don't use the endTime param
700
                        logMetacat.warn("Could not parse endTime: " + value[0]);
701
                        endTime = null;
702
                    }
703
                }
704
                else if(name.equals("objectFormat") && value != null) 
705
                {
706
                    objectFormat = ObjectFormatCache.getInstance().getFormat(value[0]);
707
                }
708
                else if(name.equals("replicaStatus") && value != null)
709
                {
710
                    if(value != null && 
711
                       value.length > 0 && 
712
                       (value[0].equals("true") || value[0].equals("TRUE") || value[0].equals("YES")))
713
                    {
714
                        replicaStatus = true;
715
                    }
716
                }
717
                else if(name.equals("start") && value != null)
718
                {
719
                    start = new Integer(value[0]).intValue();
720
                }
721
                else if(name.equals("count") && value != null)
722
                {
723
                    count = new Integer(value[0]).intValue();
724
                }
725
            }
726
            //make the crud call
727
            logMetacat.debug("session: " + session + " startTime: " + startTime +
728
                    " endtime: " + endTime + " objectFormat: " + 
729
                    objectFormat + " replicaStatus: " + replicaStatus + 
730
                    " start: " + start + " count: " + count);
731
           
732
            ObjectList ol = 
733
            	MNodeService.getInstance().listObjects(session, startTime, endTime, 
734
                    objectFormat, replicaStatus, start, count);
735
            
736
            out = response.getOutputStream();  
737
            response.setStatus(200);
738
            response.setContentType("text/xml");
739
            // Serialize and write it to the output stream
740
            serializeServiceType(ObjectList.class, ol, out);
741
            
742
        }
743
        
744
    }
745
    
746

    
747
    /**
748
     * Retrieve System Metadata
749
     * @param guid
750
     * @throws InvalidToken
751
     * @throws ServiceFailure
752
     * @throws NotAuthorized
753
     * @throws NotFound
754
     * @throws InvalidRequest
755
     * @throws NotImplemented
756
     * @throws IOException
757
     * @throws JiBXException
758
     */
759
    protected void getSystemMetadataObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
760

    
761
        Identifier id = new Identifier();
762
        id.setValue(guid);
763
        SystemMetadata sysmeta = MNodeService.getInstance().getSystemMetadata(session, id);
764
        
765
        response.setContentType("text/xml");
766
        response.setStatus(200);
767
        OutputStream out = response.getOutputStream();
768
        
769
        // Serialize and write it to the output stream
770
       serializeServiceType(SystemMetadata.class, sysmeta, out);
771
   }
772
    
773
    
774
    /**
775
     * Inserts or updates the object
776
     * 
777
     * @param guid - ID of data object to be inserted or updated.  If action is update, the pid
778
     *               is the existing pid.  If insert, the pid is the new one
779
     * @throws InvalidRequest 
780
     * @throws ServiceFailure 
781
     * @throws JiBXException 
782
     * @throws NotImplemented 
783
     * @throws InvalidSystemMetadata 
784
     * @throws InsufficientResources 
785
     * @throws UnsupportedType 
786
     * @throws IdentifierNotUnique 
787
     * @throws NotAuthorized 
788
     * @throws InvalidToken 
789
     * @throws NotFound 
790
     * @throws IOException 
791
     */
792
    protected void putObject(String pid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException {
793
        logMetacat.debug("putObject with pid " + pid);
794
        logMetacat.debug("Entering putObject: " + pid + "/" + action);
795
        
796
        response.setStatus(200);
797
        response.setContentType("text/xml");
798
        OutputStream out = response.getOutputStream();
799
        
800
        // Read the incoming data from its Mime Multipart encoding
801
    	Map<String, File> files = collectMultipartFiles();
802
        InputStream object = null;
803
        InputStream sysmeta = null;
804

    
805
        File smFile = files.get("sysmeta");
806
        sysmeta = new FileInputStream(smFile);
807
        File objFile = files.get("object");
808
        object = new FileInputStream(objFile);
809
        
810
        if (action.equals(FUNCTION_NAME_INSERT)) { 
811
            // handle inserts
812
            logMetacat.debug("Commence creation...");
813
            SystemMetadata smd = (SystemMetadata) deserializeServiceType(SystemMetadata.class, sysmeta);
814

    
815
            Identifier id = new Identifier();
816
            id.setValue(pid);
817
            logMetacat.debug("creating object with pid " + pid);
818
            Identifier rId = MNodeService.getInstance().create(session, id, object, smd);
819
            serializeServiceType(Identifier.class, rId, out);
820
            
821
        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
822
        	// handle updates
823
        	
824
            // construct pids
825
            Identifier newPid = new Identifier();
826
            try {
827
            	String newPidString = multipartparams.get("newPid").get(0);
828
                newPid.setValue(newPidString);
829
            } catch (Exception e) {
830
				logMetacat.warn("newPid not given");
831
			}
832
            
833
            Identifier obsoletedPid = new Identifier();
834
            obsoletedPid.setValue(pid);
835
           
836
            logMetacat.debug("Commence update...");
837
            
838
            // get the systemmetadata object
839
            SystemMetadata smd = (SystemMetadata) deserializeServiceType(SystemMetadata.class, sysmeta);
840

    
841
            Identifier rId = MNodeService.getInstance().update(session, newPid, object, obsoletedPid, smd);
842
            serializeServiceType(Identifier.class, rId, out);
843
        } else {
844
            throw new InvalidRequest("1000", "Operation must be create or update.");
845
        }
846
            
847
            
848
    }
849

    
850
    /**
851
     * Handle delete 
852
     * @param guid ID of data object to be deleted
853
     * @throws IOException
854
     * @throws InvalidRequest 
855
     * @throws NotImplemented 
856
     * @throws NotFound 
857
     * @throws NotAuthorized 
858
     * @throws ServiceFailure 
859
     * @throws InvalidToken 
860
     * @throws JiBXException 
861
     */
862
    private void deleteObject(String guid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
863
    {
864

    
865
        OutputStream out = response.getOutputStream();
866
        response.setStatus(200);
867
        response.setContentType("text/xml");
868

    
869
        Identifier id = new Identifier();
870
        id.setValue(guid);
871

    
872
        logMetacat.debug("Calling delete");
873
        MNodeService.getInstance().delete(session, id);
874
        serializeServiceType(Identifier.class, id, out);
875
        
876
    }    
877
    
878
    /**
879
     * set the access perms on a document
880
     * @throws JiBXException 
881
     * @throws UnsupportedEncodingException 
882
     * @throws InvalidRequest 
883
     * @throws NotImplemented 
884
     * @throws NotAuthorized 
885
     * @throws NotFound 
886
     * @throws ServiceFailure 
887
     * @throws InvalidToken 
888
     */
889
    protected void setAccess() throws UnsupportedEncodingException, JiBXException, InvalidToken, ServiceFailure, NotFound, NotAuthorized, NotImplemented, InvalidRequest
890
    {
891
    
892
        String guid = params.get("guid")[0];
893
        Identifier id = new Identifier();
894
        id.setValue(guid);
895
        String accesspolicy = params.get("accesspolicy")[0];
896
        AccessPolicy accessPolicy = (AccessPolicy) deserializeServiceType(AccessPolicy.class, new ByteArrayInputStream(accesspolicy.getBytes("UTF-8")));
897
        MNodeService.getInstance().setAccessPolicy(session, id, accessPolicy);
898
        
899
        
900
    }
901

    
902
}
(8-8/11)