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-07-01 17:23:13 -0700 (Fri, 01 Jul 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
        	// get the resource
144
            String resource = request.getPathInfo();
145
            resource = resource.substring(resource.indexOf("/") + 1);
146
            
147
            // default to node info
148
            if (resource.equals("")) {
149
                resource = RESOURCE_NODE;
150
            }
151
            
152
            // get the rest of the path info
153
            String extra = null;
154
            if (resource.lastIndexOf("/") != -1) {
155
                extra = resource.substring(resource.lastIndexOf("/") + 1);
156
            }
157
                        
158
            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
159
            logMetacat.debug("resource: '" + resource + "'");
160
            boolean status = false;
161
            
162
            if (resource != null) {
163

    
164
                if (resource.startsWith(RESOURCE_NODE)) {
165
                    // node response
166
                    node();
167
                    status = true;
168
                } else if (resource.startsWith(RESOURCE_ACCESS_RULES)) {
169
                    if (httpVerb == POST) {
170
	                	// set the access rules
171
	                    setAccess();
172
	                    status = true;
173
	                    logMetacat.debug("done setting access");
174
                    }
175
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
176
                    if (httpVerb == GET) {
177
	                	// check the access rules
178
	                    isAuthorized(extra);
179
	                    status = true;
180
	                    logMetacat.debug("done getting access");
181
                    }
182
                } else if (resource.startsWith(RESOURCE_META)) {
183
                    logMetacat.debug("Using resource 'meta'");
184
                    // get
185
                    if (httpVerb == GET) {
186
                        getSystemMetadataObject(extra);
187
                        status = true;
188
                    }
189
                    
190
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
191
                    logMetacat.debug("Using resource 'object'");
192
                    
193
                    logMetacat.debug("objectId: " + extra);
194
                    logMetacat.debug("verb:" + httpVerb);
195

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

    
379
            if (params.containsKey("format")) {
380
                String f = params.get("format")[0];
381
                format = ObjectFormatCache.getInstance().getFormat(f);
382
            }
383
            if (params.containsKey("period")) {
384
                String t = params.get("period")[0];
385
                period = Integer.valueOf(t);
386
            }
387
            if (params.containsKey("requestor")) {
388
            	requestor = params.get("requestor")[0];
389
            	subject = new Subject();
390
            	subject.setValue(requestor);
391
            }
392
            if (params.containsKey("event")) {
393
            	eventName = params.get("event")[0];
394
                event = Event.valueOf(eventName);
395
            }
396
            
397
            MonitorList monitorList = MNodeService.getInstance().getOperationStatistics(session, period, subject, event, format);
398
            
399
            OutputStream out = response.getOutputStream();
400
            response.setStatus(200);
401
            response.setContentType("text/xml");
402
            
403
            serializeServiceType(MonitorList.class, monitorList, out);
404
            
405
            return true;
406
            
407
        }
408
        
409
        return false;
410
    }
411
    
412
    /**
413
     * Calculate the checksum 
414
     * @throws NotImplemented
415
     * @throws JiBXException
416
     * @throws IOException
417
     * @throws InvalidToken
418
     * @throws ServiceFailure
419
     * @throws NotAuthorized
420
     * @throws NotFound
421
     * @throws InvalidRequest
422
     */
423
    private void checksum(String guid) throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
424
    	String checksumAlgorithm = "MD5";
425
        
426
        Identifier guidid = new Identifier();
427
        guidid.setValue(guid);
428
        try {
429
            checksumAlgorithm = params.get("checksumAlgorithm")[0];
430
        } catch(Exception e) {
431
            //do nothing.  default to MD5
432
        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
433
        }
434
        logMetacat.debug("getting checksum for object " + guid + " with algorithm " + checksumAlgorithm);
435
        
436
        Checksum c = MNodeService.getInstance().getChecksum(session, guidid, checksumAlgorithm);
437
        logMetacat.debug("got checksum " + c.getValue());
438
        response.setStatus(200);
439
        logMetacat.debug("serializing response");
440
        serializeServiceType(Checksum.class, c, response.getOutputStream());
441
        logMetacat.debug("done serializing response.");
442
        
443
    }
444
    
445
	/**
446
     * handle the replicate action for MN
447
	 * @throws JiBXException 
448
	 * @throws FileUploadException 
449
	 * @throws IOException 
450
	 * @throws InvalidRequest 
451
	 * @throws ServiceFailure 
452
	 * @throws UnsupportedType 
453
	 * @throws InsufficientResources 
454
	 * @throws NotAuthorized 
455
	 * @throws NotImplemented 
456
     */
457
    private void replicate() throws ServiceFailure, InvalidRequest, IOException, FileUploadException, JiBXException, NotImplemented, NotAuthorized, InsufficientResources, UnsupportedType {
458

    
459
        logMetacat.debug("in POST replicate()");
460
        
461
        //parse the systemMetadata
462
        SystemMetadata sysmeta = collectSystemMetadata();
463
        
464
        String sn = multipartparams.get("sourceNode").get(0);
465
        logMetacat.debug("sourceNode: " + sn);
466
        NodeReference sourceNode = (NodeReference) deserializeServiceType(NodeReference.class, new ByteArrayInputStream(sn.getBytes("UTF-8")));
467
        
468
        MNodeService.getInstance().replicate(session, sysmeta, sourceNode);
469

    
470
        response.setStatus(200);
471

    
472
    }
473
    
474
    /**
475
     * Get the Node information
476
     * 
477
     * @throws JiBXException
478
     * @throws IOException
479
     * @throws InvalidRequest 
480
     * @throws ServiceFailure 
481
     * @throws NotAuthorized 
482
     * @throws NotImplemented 
483
     */
484
    private void node() 
485
        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
486
        
487
        Node n = MNodeService.getInstance().getCapabilities();
488
        
489
        NodeList nl = new NodeList();
490
        nl.addNode(n);
491
        
492
        response.setContentType("text/xml");
493
        response.setStatus(200);
494
        serializeServiceType(NodeList.class, nl, response.getOutputStream());
495
        
496
    }
497
    
498
    /**
499
     * MN_crud.describe()
500
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
501
     * @param guid
502
     * @throws InvalidRequest 
503
     * @throws NotImplemented 
504
     * @throws NotFound 
505
     * @throws NotAuthorized 
506
     * @throws ServiceFailure 
507
     * @throws InvalidToken 
508
     */
509
    private void describeObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
510
    {
511
        response.setStatus(200);
512
        response.setContentType("text/xml");
513
        
514
        Identifier id = new Identifier();
515
        id.setValue(guid);
516

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

    
640
            out = response.getOutputStream();  
641
            IOUtils.copyLarge(data, out);
642
            
643
        }
644
        else
645
        { //call listObjects with specified params
646
            Date startTime = null;
647
            Date endTime = null;
648
            ObjectFormat objectFormat = null;
649
            boolean replicaStatus = false;
650
            int start = 0;
651
            //TODO: make the max count into a const
652
            int count = 1000;
653
            Enumeration paramlist = request.getParameterNames();
654
            while (paramlist.hasMoreElements()) 
655
            { //parse the params and make the crud call
656
                String name = (String) paramlist.nextElement();
657
                String[] value = (String[])request.getParameterValues(name);
658

    
659
                if (name.equals("startTime") && value != null)
660
                {
661
                    try
662
                    {
663
                      //startTime = dateFormat.parse(value[0]);
664
                        startTime = parseDateAndConvertToGMT(value[0]);
665
                    }
666
                    catch(Exception e)
667
                    {  //if we can't parse it, just don't use the startTime param
668
                        logMetacat.warn("Could not parse startTime: " + value[0]);
669
                        startTime = null;
670
                    }
671
                }
672
                else if(name.equals("endTime") && value != null)
673
                {
674
                    try
675
                    {
676
                      //endTime = dateFormat.parse(value[0]);
677
                        endTime = parseDateAndConvertToGMT(value[0]);
678
                    }
679
                    catch(Exception e)
680
                    {  //if we can't parse it, just don't use the endTime param
681
                        logMetacat.warn("Could not parse endTime: " + value[0]);
682
                        endTime = null;
683
                    }
684
                }
685
                else if(name.equals("objectFormat") && value != null) 
686
                {
687
                    objectFormat = ObjectFormatCache.getInstance().getFormat(value[0]);
688
                }
689
                else if(name.equals("replicaStatus") && value != null)
690
                {
691
                    if(value != null && 
692
                       value.length > 0 && 
693
                       (value[0].equals("true") || value[0].equals("TRUE") || value[0].equals("YES")))
694
                    {
695
                        replicaStatus = true;
696
                    }
697
                }
698
                else if(name.equals("start") && value != null)
699
                {
700
                    start = new Integer(value[0]).intValue();
701
                }
702
                else if(name.equals("count") && value != null)
703
                {
704
                    count = new Integer(value[0]).intValue();
705
                }
706
            }
707
            //make the crud call
708
            logMetacat.debug("session: " + session + " startTime: " + startTime +
709
                    " endtime: " + endTime + " objectFormat: " + 
710
                    objectFormat + " replicaStatus: " + replicaStatus + 
711
                    " start: " + start + " count: " + count);
712
           
713
            ObjectList ol = 
714
            	MNodeService.getInstance().listObjects(session, startTime, endTime, 
715
                    objectFormat, replicaStatus, start, count);
716
            
717
            out = response.getOutputStream();  
718
            response.setStatus(200);
719
            response.setContentType("text/xml");
720
            // Serialize and write it to the output stream
721
            serializeServiceType(ObjectList.class, ol, out);
722
            
723
        }
724
        
725
    }
726
    
727

    
728
    /**
729
     * Retrieve System Metadata
730
     * @param guid
731
     * @throws InvalidToken
732
     * @throws ServiceFailure
733
     * @throws NotAuthorized
734
     * @throws NotFound
735
     * @throws InvalidRequest
736
     * @throws NotImplemented
737
     * @throws IOException
738
     * @throws JiBXException
739
     */
740
    protected void getSystemMetadataObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
741

    
742
        Identifier id = new Identifier();
743
        id.setValue(guid);
744
        SystemMetadata sysmeta = MNodeService.getInstance().getSystemMetadata(session, id);
745
        
746
        response.setContentType("text/xml");
747
        response.setStatus(200);
748
        OutputStream out = response.getOutputStream();
749
        
750
        // Serialize and write it to the output stream
751
       serializeServiceType(SystemMetadata.class, sysmeta, out);
752
   }
753
    
754
    
755
    /**
756
     * Inserts or updates the object
757
     * 
758
     * @param guid - ID of data object to be inserted or updated.  If action is update, the pid
759
     *               is the existing pid.  If insert, the pid is the new one
760
     * @throws InvalidRequest 
761
     * @throws ServiceFailure 
762
     * @throws JiBXException 
763
     * @throws NotImplemented 
764
     * @throws InvalidSystemMetadata 
765
     * @throws InsufficientResources 
766
     * @throws UnsupportedType 
767
     * @throws IdentifierNotUnique 
768
     * @throws NotAuthorized 
769
     * @throws InvalidToken 
770
     * @throws NotFound 
771
     * @throws IOException 
772
     */
773
    protected void putObject(String pid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException {
774
        logMetacat.debug("putObject with pid " + pid);
775
        logMetacat.debug("Entering putObject: " + pid + "/" + action);
776
        
777
        response.setStatus(200);
778
        response.setContentType("text/xml");
779
        OutputStream out = response.getOutputStream();
780
        
781
        // Read the incoming data from its Mime Multipart encoding
782
    	Map<String, File> files = collectMultipartFiles();
783
        InputStream object = null;
784
        InputStream sysmeta = null;
785

    
786
        File smFile = files.get("sysmeta");
787
        sysmeta = new FileInputStream(smFile);
788
        File objFile = files.get("object");
789
        object = new FileInputStream(objFile);
790
        
791
        if (action.equals(FUNCTION_NAME_INSERT)) { 
792
            // handle inserts
793
            logMetacat.debug("Commence creation...");
794
            SystemMetadata smd = (SystemMetadata) deserializeServiceType(SystemMetadata.class, sysmeta);
795

    
796
            Identifier id = new Identifier();
797
            id.setValue(pid);
798
            logMetacat.debug("creating object with pid " + pid);
799
            Identifier rId = MNodeService.getInstance().create(session, id, object, smd);
800
            serializeServiceType(Identifier.class, rId, out);
801
            
802
        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
803
        	// handle updates
804
        	
805
            // construct pids
806
            Identifier newPid = new Identifier();
807
            try {
808
            	String newPidString = multipartparams.get("newPid").get(0);
809
                newPid.setValue(newPidString);
810
            } catch (Exception e) {
811
				logMetacat.warn("newPid not given");
812
			}
813
            
814
            Identifier obsoletedPid = new Identifier();
815
            obsoletedPid.setValue(pid);
816
           
817
            logMetacat.debug("Commence update...");
818
            
819
            // get the systemmetadata object
820
            SystemMetadata smd = (SystemMetadata) deserializeServiceType(SystemMetadata.class, sysmeta);
821

    
822
            Identifier rId = MNodeService.getInstance().update(session, newPid, object, obsoletedPid, smd);
823
            serializeServiceType(Identifier.class, rId, out);
824
        } else {
825
            throw new InvalidRequest("1000", "Operation must be create or update.");
826
        }
827
            
828
            
829
    }
830

    
831
    /**
832
     * Handle delete 
833
     * @param guid ID of data object to be deleted
834
     * @throws IOException
835
     * @throws InvalidRequest 
836
     * @throws NotImplemented 
837
     * @throws NotFound 
838
     * @throws NotAuthorized 
839
     * @throws ServiceFailure 
840
     * @throws InvalidToken 
841
     * @throws JiBXException 
842
     */
843
    private void deleteObject(String guid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException 
844
    {
845

    
846
        OutputStream out = response.getOutputStream();
847
        response.setStatus(200);
848
        response.setContentType("text/xml");
849

    
850
        Identifier id = new Identifier();
851
        id.setValue(guid);
852

    
853
        logMetacat.debug("Calling delete");
854
        MNodeService.getInstance().delete(session, id);
855
        serializeServiceType(Identifier.class, id, out);
856
        
857
    }    
858
    
859
    /**
860
     * set the access perms on a document
861
     * @throws JiBXException 
862
     * @throws UnsupportedEncodingException 
863
     * @throws InvalidRequest 
864
     * @throws NotImplemented 
865
     * @throws NotAuthorized 
866
     * @throws NotFound 
867
     * @throws ServiceFailure 
868
     * @throws InvalidToken 
869
     */
870
    protected void setAccess() throws UnsupportedEncodingException, JiBXException, InvalidToken, ServiceFailure, NotFound, NotAuthorized, NotImplemented, InvalidRequest
871
    {
872
    
873
        String guid = params.get("guid")[0];
874
        Identifier id = new Identifier();
875
        id.setValue(guid);
876
        String accesspolicy = params.get("accesspolicy")[0];
877
        AccessPolicy accessPolicy = (AccessPolicy) deserializeServiceType(AccessPolicy.class, new ByteArrayInputStream(accesspolicy.getBytes("UTF-8")));
878
        MNodeService.getInstance().setAccessPolicy(session, id, accessPolicy);
879
        
880
        
881
    }
882

    
883
}
(8-8/11)