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: cjones $'
7
 *     '$Date: 2011-11-04 14:19:37 -0700 (Fri, 04 Nov 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.util.Date;
32
import java.util.Map;
33

    
34
import javax.servlet.ServletContext;
35
import javax.servlet.http.HttpServletRequest;
36
import javax.servlet.http.HttpServletResponse;
37
import javax.xml.parsers.ParserConfigurationException;
38

    
39
import org.apache.commons.fileupload.FileUploadException;
40
import org.apache.commons.io.IOUtils;
41
import org.apache.log4j.Logger;
42
import org.dataone.client.ObjectFormatCache;
43
import org.dataone.service.exceptions.BaseException;
44
import org.dataone.service.exceptions.IdentifierNotUnique;
45
import org.dataone.service.exceptions.InsufficientResources;
46
import org.dataone.service.exceptions.InvalidRequest;
47
import org.dataone.service.exceptions.InvalidSystemMetadata;
48
import org.dataone.service.exceptions.InvalidToken;
49
import org.dataone.service.exceptions.NotAuthorized;
50
import org.dataone.service.exceptions.NotFound;
51
import org.dataone.service.exceptions.NotImplemented;
52
import org.dataone.service.exceptions.ServiceFailure;
53
import org.dataone.service.exceptions.UnsupportedType;
54
import org.dataone.service.types.v1.AccessPolicy;
55
import org.dataone.service.types.v1.Checksum;
56
import org.dataone.service.types.v1.Event;
57
import org.dataone.service.types.v1.Identifier;
58
import org.dataone.service.types.v1.Log;
59
import org.dataone.service.types.v1.NodeReference;
60
import org.dataone.service.types.v1.ObjectFormat;
61
import org.dataone.service.types.v1.ObjectFormatIdentifier;
62
import org.dataone.service.types.v1.ObjectFormatList;
63
import org.dataone.service.types.v1.ObjectLocationList;
64
import org.dataone.service.types.v1.Permission;
65
import org.dataone.service.types.v1.Replica;
66
import org.dataone.service.types.v1.ReplicationPolicy;
67
import org.dataone.service.types.v1.ReplicationStatus;
68
import org.dataone.service.types.v1.Session;
69
import org.dataone.service.types.v1.Subject;
70
import org.dataone.service.types.v1.SystemMetadata;
71
import org.dataone.service.util.DateTimeMarshaller;
72
import org.dataone.service.util.TypeMarshaller;
73
import org.jibx.runtime.JiBXException;
74
import org.xml.sax.SAXException;
75

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

    
78
/**
79
 * CN REST service implementation handler
80
 * 
81
 * ******************
82
 	CNCore -- DONE
83
		create() - POST /d1/cn/object/PID
84
		listFormats() - GET /d1/cn/formats
85
		getFormat() - GET /d1/cn/formats/FMTID
86
		getLogRecords - GET /d1/cn/log
87
		reserveIdentifier() - POST /d1/cn/reserve
88
		listNodes() - Not implemented
89
		registerSystemMetadata() - POST /d1/meta/PID
90
	
91
	CNRead -- DONE
92
		get() - GET /d1/cn/object/PID
93
		getSystemMetadata() - GET /d1/cn/meta/PID
94
		resolve() - GET /d1/cn/resolve/PID
95
		assertRelation() - GET /d1/cn/assertRelation/PID
96
		getChecksum() - GET /d1/cn/checksum
97
		search() - Not implemented in Metacat
98
	
99
	CNAuthorization
100
		setOwner() - PUT /d1/cn/owner/PID
101
		isAuthorized() - GET /d1/cn/isAuthorized/PID
102
		setAccessPolicy() - POST /d1/cn/accessRules
103
		
104
	CNIdentity - not implemented at all on Metacat
105
	
106
	CNReplication
107
		setReplicationStatus() - PUT /replicationNotifications/PID
108
		updateReplicationMetadata() - PUT /replicationMetadata/PID
109
		setReplicationPolicy() - PUT /replicationPolicies/PID
110
		isNodeAuthorized() - GET /replicationAuthorizations/PID
111
	
112
	CNRegister -- not implemented at all in Metacat
113
 * ******************
114
 * @author leinfelder
115
 *
116
 */
117
public class CNResourceHandler extends D1ResourceHandler {
118

    
119
	/** CN-specific operations **/
120
    protected static final String RESOURCE_RESERVE = "reserve";
121
    protected static final String RESOURCE_FORMATS = "formats";
122
    protected static final String RESOURCE_RESOLVE = "resolve";
123
    protected static final String RESOURCE_ASSERT_RELATION = "assertRelation";
124
    protected static final String RESOURCE_OWNER = "owner";
125
    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
126
    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
127
    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
128
    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
129
	
130
    public CNResourceHandler(ServletContext servletContext,
131
			HttpServletRequest request, HttpServletResponse response) {
132
		super(servletContext, request, response);
133
        logMetacat = Logger.getLogger(CNResourceHandler.class);
134
	}
135

    
136
	/**
137
     * This function is called from REST API servlet and handles each request to the servlet 
138
     * 
139
     * @param httpVerb (GET, POST, PUT or DELETE)
140
     */
141
    @Override
142
    public void handle(byte httpVerb) {
143
    	// prepare the handler
144
    	super.handle(httpVerb);
145
    	
146
        try {
147

    
148
        	// get the resource
149
            String resource = request.getPathInfo();
150
            resource = resource.substring(resource.indexOf("/") + 1);
151
                        
152
            // for the rest of the resouce
153
            String extra = null;
154
            
155
            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
156
            boolean status = false;
157

    
158
            if (resource != null) {
159

    
160
                if (resource.startsWith(RESOURCE_ACCESS_RULES) && httpVerb == PUT) {
161
                    logMetacat.debug("Setting access policy");
162
                    // after the command
163
                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
164
                    setAccess(extra);
165
                    status = true;
166
                    logMetacat.debug("done setting access");
167
                    
168
                } else if (resource.startsWith(RESOURCE_META)) {
169
                    logMetacat.debug("Using resource: " + RESOURCE_META);
170
                    
171
                    // after the command
172
                    extra = parseTrailing(resource, RESOURCE_META);
173
                    
174
                    // get
175
                    if (httpVerb == GET) {
176
                        getSystemMetadataObject(extra);
177
                        status = true;
178
                    }
179
                    // post to register system metadata
180
                    if (httpVerb == POST) {
181
                    	registerSystemMetadata(extra);
182
                    	status = true;
183
                    }
184

    
185
                } else if (resource.startsWith(RESOURCE_RESERVE)) {
186
                    // reserve the ID (in params)
187
                    if (httpVerb == POST) {
188
                    	reserve();
189
                    	status = true;
190
                    }
191
                } else if (resource.startsWith(RESOURCE_ASSERT_RELATION)) {
192
                	
193
                	// after the command
194
                    extra = parseTrailing(resource, RESOURCE_ASSERT_RELATION);
195
                    
196
                    // reserve the ID (in params)
197
                    if (httpVerb == GET) {
198
                    	assertRelation(extra);
199
                    	status = true;
200
                    }    
201
                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
202
                	
203
                	// after the command
204
                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
205
                    
206
                    // resolve the object location
207
                    if (httpVerb == GET) {
208
                    	resolve(extra);
209
                    	status = true;
210
                    }
211
                } else if (resource.startsWith(RESOURCE_OWNER)) {
212
                	
213
                	// after the command
214
                    extra = parseTrailing(resource, RESOURCE_OWNER);
215
                    
216
                    // set the owner
217
                    if (httpVerb == PUT) {
218
                    	owner(extra);
219
                    	status = true;
220
                    }    
221
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
222
                	
223
                	// after the command
224
                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
225
                    
226
                    // authorized?
227
                    if (httpVerb == GET) {
228
                    	isAuthorized(extra);
229
                    	status = true;
230
                    }    
231
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
232
                    logMetacat.debug("Using resource 'object'");
233
                    logMetacat.debug("D1 Rest: Starting resource processing...");
234
                    
235
                    // after the command
236
                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
237
                    
238
                    logMetacat.debug("objectId: " + extra);
239
                    logMetacat.debug("verb:" + httpVerb);
240

    
241
                    if (httpVerb == GET) {
242
                    	if (extra != null) {
243
                    		getObject(extra);
244
                    	} else {
245
                    		query();
246
                    	}
247
                        status = true;
248
                    } else if (httpVerb == POST) {
249
                        putObject(extra, FUNCTION_NAME_INSERT);
250
                        status = true;
251
                    }
252
                    
253
                } else if (resource.startsWith(RESOURCE_FORMATS)) {
254
                  logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
255
                  
256
                  // after the command
257
                  extra = parseTrailing(resource, RESOURCE_FORMATS);
258
                  
259
                  // handle each verb
260
                  if (httpVerb == GET) {
261
                  	if (extra == null) {
262
                  		// list the formats collection
263
                  		listFormats();
264
                  	} else {
265
                  		// get the specified format
266
                  		getFormat(extra);
267
                  	}
268
                  	status = true;
269
                  }
270
                  
271
                } else if (resource.startsWith(RESOURCE_LOG)) {
272
                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
273
                    //handle log events
274
                    if (httpVerb == GET) {
275
                        getLog();
276
                        status = true;
277
                    }
278

    
279
                } else if (resource.startsWith(RESOURCE_CHECKSUM)) {
280
                    logMetacat.debug("Using resource: " + RESOURCE_CHECKSUM);
281
                    
282
                    // after the command
283
                    extra = parseTrailing(resource, RESOURCE_CHECKSUM);
284
                    
285
                    //handle checksum requests
286
                    if (httpVerb == GET) {
287
                    
288
                        checksum(extra);
289
                        status = true;
290
                        
291
                    }
292
                
293
                } else if ( resource.startsWith(RESOURCE_REPLICATION_POLICY) && 
294
                        httpVerb == PUT) {
295
                    
296
                    logMetacat.debug("Using resource: " + RESOURCE_REPLICATION_POLICY);
297
                    // get the trailing pid
298
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
299
                    setReplicationPolicy(extra);
300
                    status = true;
301

    
302
                } else if ( resource.startsWith(RESOURCE_REPLICATION_META) && 
303
                        httpVerb == PUT) {
304
                    
305
                    logMetacat.debug("Using resource: " + RESOURCE_REPLICATION_META);
306
                    // get the trailing pid
307
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
308
                    updateReplicationMetadata(extra);
309
                    status = true;
310

    
311
                } else if ( resource.startsWith(RESOURCE_REPLICATION_NOTIFY) && 
312
                        httpVerb == PUT ) {
313
                    
314
                    logMetacat.debug("Using resource: " + RESOURCE_REPLICATION_NOTIFY);
315
                    // get the trailing pid
316
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
317
                    setReplicationStatus(extra);
318
                    status = true;
319
                    
320
                } else if ( resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED) 
321
                        && httpVerb == GET) {
322
                    
323
                    logMetacat.debug("Using resource: " + RESOURCE_REPLICATION_AUTHORIZED);
324
                    // get the trailing pid
325
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_AUTHORIZED);
326
                    isNodeAuthorized(extra);
327
                    status = true;
328
                    
329
                } 
330
                    
331
                if (!status) {
332
                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
333
                }
334
            } else {
335
            	throw new InvalidRequest("0000", "No resource matched for " + resource);
336
            }
337
        } catch (BaseException be) {
338
        	// report Exceptions as clearly and generically as possible
339
        	OutputStream out = null;
340
			try {
341
				out = response.getOutputStream();
342
			} catch (IOException ioe) {
343
				logMetacat.error("Could not get output stream from response", ioe);
344
			}
345
            serializeException(be, out);
346
        } catch (Exception e) {
347
            // report Exceptions as clearly and generically as possible
348
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
349
        	OutputStream out = null;
350
			try {
351
				out = response.getOutputStream();
352
			} catch (IOException ioe) {
353
				logMetacat.error("Could not get output stream from response", ioe);
354
			}
355
			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
356
            serializeException(se, out);
357
        }
358
    }
359
    
360
    
361
    /**
362
     * Get the checksum for the given guid
363
     * 
364
     * @param guid
365
     * @throws NotImplemented 
366
     * @throws InvalidRequest 
367
     * @throws NotFound 
368
     * @throws NotAuthorized 
369
     * @throws ServiceFailure 
370
     * @throws InvalidToken 
371
     * @throws IOException 
372
     * @throws JiBXException 
373
     */
374
    private void checksum(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, JiBXException, IOException {
375
    	Identifier guidid = new Identifier();
376
        guidid.setValue(guid);
377
        logMetacat.debug("getting checksum for object " + guid);
378
        Checksum c = CNodeService.getInstance(request).getChecksum(session, guidid);
379
        logMetacat.debug("got checksum " + c.getValue());
380
        response.setStatus(200);
381
        logMetacat.debug("serializing response");
382
        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
383
        logMetacat.debug("done serializing response.");
384
        
385
    }
386
    
387
	/**
388
     * get the logs based on passed params.  Available 
389
     * params are token, fromDate, toDate, event.  See 
390
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
391
     * for more info
392
	 * @throws NotImplemented 
393
	 * @throws InvalidRequest 
394
	 * @throws NotAuthorized 
395
	 * @throws ServiceFailure 
396
	 * @throws InvalidToken 
397
	 * @throws IOException 
398
	 * @throws JiBXException 
399
     */
400
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
401
    {
402
        
403
        Date fromDate = null;
404
        Date toDate = null;
405
        Event event = null;
406
        Integer start = null;
407
        Integer count = null;
408
        
409
        try {
410
        	String fromDateS = params.get("fromDate")[0];
411
            logMetacat.debug("param fromDateS: " + fromDateS);
412
            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
413
        } catch (Exception e) {
414
        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
415
        }
416
        try {
417
        	String toDateS = params.get("toDate")[0];
418
            logMetacat.debug("param toDateS: " + toDateS);
419
            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
420
        } catch (Exception e) {
421
        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
422
		}
423
        try {
424
        	String eventS = params.get("event")[0];
425
            event = Event.convert(eventS);
426
        } catch (Exception e) {
427
        	logMetacat.warn("Could not parse event: " + e.getMessage());
428
		}
429
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
430
        
431
        try {
432
        	start =  Integer.parseInt(params.get("start")[0]);
433
        } catch (Exception e) {
434
			logMetacat.warn("Could not parse start: " + e.getMessage());
435
		}
436
        try {
437
        	count =  Integer.parseInt(params.get("count")[0]);
438
        } catch (Exception e) {
439
			logMetacat.warn("Could not parse count: " + e.getMessage());
440
		}
441
        
442
        logMetacat.debug("calling getLogRecords");
443
        Log log = CNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, event, start, count);
444
        
445
        OutputStream out = response.getOutputStream();
446
        response.setStatus(200);
447
        response.setContentType("text/xml");
448
        
449
        TypeMarshaller.marshalTypeToOutputStream(log, out);
450
  
451
    }
452

    
453
    /**
454
     * Implements REST version of DataONE CRUD API --> get
455
     * @param guid ID of data object to be read
456
     * @throws NotImplemented 
457
     * @throws InvalidRequest 
458
     * @throws NotFound 
459
     * @throws NotAuthorized 
460
     * @throws ServiceFailure 
461
     * @throws InvalidToken 
462
     * @throws IOException 
463
     */
464
    protected void getObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException {
465

    
466
        Identifier id = new Identifier();
467
        id.setValue(guid);
468
            
469
        SystemMetadata sm = CNodeService.getInstance(request).getSystemMetadata(session, id);
470
        
471
        //set the content type
472
        if(sm.getFormatId().getValue().trim().equals(
473
        		ObjectFormatCache.getInstance().getFormat("text/csv").getFormatId().getValue()))
474
        {
475
            response.setContentType("text/csv");
476
            response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".csv");
477
        }
478
        else if(sm.getFormatId().getValue().trim().equals(
479
        		ObjectFormatCache.getInstance().getFormat("text/plain").getFormatId().getValue()))
480
        {
481
            response.setContentType("text/plain");
482
            response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".txt");
483
        } 
484
        else if(sm.getFormatId().getValue().trim().equals(
485
        		ObjectFormatCache.getInstance().getFormat("application/octet-stream").getFormatId().getValue()))
486
        {
487
            response.setContentType("application/octet-stream");
488
        }
489
        else
490
        {
491
            response.setContentType("text/xml");
492
            response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".xml");
493
        }
494
        
495
        InputStream data = CNodeService.getInstance(request).get(session, id);
496
        
497
        OutputStream out = response.getOutputStream();
498
        response.setStatus(200);
499
        IOUtils.copyLarge(data, out);
500
            
501
    }
502
    
503

    
504
    /**
505
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
506
     * @param guid ID of data object to be read
507
     * @throws NotImplemented 
508
     * @throws InvalidRequest 
509
     * @throws NotFound 
510
     * @throws NotAuthorized 
511
     * @throws ServiceFailure 
512
     * @throws InvalidToken 
513
     * @throws IOException 
514
     * @throws JiBXException 
515
     */
516
    protected void getSystemMetadataObject(String guid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
517

    
518
        Identifier id = new Identifier();
519
        id.setValue(guid);
520
        SystemMetadata sysmeta = CNodeService.getInstance(request).getSystemMetadata(session, id);
521
        
522
        response.setContentType("text/xml");
523
        response.setStatus(200);
524
        OutputStream out = response.getOutputStream();
525
        
526
        // Serialize and write it to the output stream
527
        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
528
   }
529
    
530
    /**
531
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction 
532
     * 
533
     * @param guid - ID of data object to be inserted or updated.  If action is update, the pid
534
     *               is the existing pid.  If insert, the pid is the new one
535
     * @throws InvalidRequest 
536
     * @throws ServiceFailure 
537
     * @throws IdentifierNotUnique 
538
     * @throws JiBXException 
539
     * @throws NotImplemented 
540
     * @throws InvalidSystemMetadata 
541
     * @throws InsufficientResources 
542
     * @throws UnsupportedType 
543
     * @throws NotAuthorized 
544
     * @throws InvalidToken 
545
     * @throws IOException 
546
     * @throws IllegalAccessException 
547
     * @throws InstantiationException 
548
     */
549
    protected void putObject(String pid, String action) throws ServiceFailure, InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken, NotAuthorized, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, IOException, InstantiationException, IllegalAccessException {
550
        logMetacat.debug("Entering putObject: " + pid + "/" + action);
551
        
552
        // Read the incoming data from its Mime Multipart encoding
553
    	Map<String, File> files = collectMultipartFiles();
554
        InputStream object = null;
555
        InputStream sysmeta = null;
556

    
557
        File smFile = files.get("sysmeta");
558
        sysmeta = new FileInputStream(smFile);
559
        File objFile = files.get("object");
560
        object = new FileInputStream(objFile);
561
       
562
        if (action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
563

    
564
            logMetacat.debug("Commence creation...");
565
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
566

    
567
            Identifier id = new Identifier();
568
            id.setValue(pid);
569
            logMetacat.debug("creating object with pid " + id.getValue());
570
            Identifier rId = CNodeService.getInstance(request).create(session, id, object, smd);
571
            
572
            OutputStream out = response.getOutputStream();
573
            response.setStatus(200);
574
            response.setContentType("text/xml");
575
            
576
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
577
            
578
        } else {
579
            throw new InvalidRequest("1000", "Operation must be create.");
580
        }
581
    }
582

    
583
    /**
584
     * List the object formats registered with the system
585
     * @throws NotImplemented 
586
     * @throws InsufficientResources 
587
     * @throws NotFound 
588
     * @throws ServiceFailure 
589
     * @throws InvalidRequest 
590
     * @throws IOException 
591
     * @throws JiBXException 
592
     */
593
	private void listFormats() throws InvalidRequest, ServiceFailure, NotFound, InsufficientResources, NotImplemented, IOException, JiBXException {
594
      logMetacat.debug("Entering listFormats()");
595

    
596
      ObjectFormatList objectFormatList = CNodeService.getInstance(request).listFormats();
597
      // get the response output stream
598
      OutputStream out = response.getOutputStream();
599
      response.setStatus(200);
600
      response.setContentType("text/xml");
601
      
602
      TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out);
603
            
604
    }
605

    
606
		/**
607
     * Return the requested object format
608
     * 
609
     * @param fmtidStr the requested format identifier as a string
610
		 * @throws NotImplemented 
611
		 * @throws InsufficientResources 
612
		 * @throws NotFound 
613
		 * @throws ServiceFailure 
614
		 * @throws InvalidRequest 
615
		 * @throws IOException 
616
		 * @throws JiBXException 
617
     */
618
    private void getFormat(String fmtidStr) throws InvalidRequest, ServiceFailure, NotFound, InsufficientResources, NotImplemented, IOException, JiBXException {
619
      logMetacat.debug("Entering listFormats()");
620
      
621
      ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
622
      fmtid.setValue(fmtidStr);
623
      
624
	  // get the specified object format
625
      ObjectFormat objectFormat = CNodeService.getInstance(request).getFormat(fmtid);
626
      
627
      OutputStream out = response.getOutputStream();
628
      response.setStatus(200);
629
      response.setContentType("text/xml");
630
      
631
      TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
632
      
633
    }
634
    
635
    /**
636
     * Reserve the given Identifier
637
     * @throws InvalidToken
638
     * @throws ServiceFailure
639
     * @throws NotAuthorized
640
     * @throws IdentifierNotUnique
641
     * @throws NotImplemented
642
     * @throws InvalidRequest
643
     * @throws IOException 
644
     * @throws JiBXException 
645
     */
646
    private void reserve() throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, NotImplemented, InvalidRequest, IOException, JiBXException {
647
		Identifier pid = null;
648
		String scope = null;
649
    	String format = null;
650
    	// gather the params
651
		try {
652
	    	String id = params.get("pid")[0];
653
			pid = new Identifier();
654
			pid.setValue(id);
655
		} catch (Exception e) {
656
			logMetacat.warn("pid not specified");
657
		}
658
		try {
659
			scope = params.get("scope")[0];
660
		} catch (Exception e) {
661
			logMetacat.warn("pid not specified");
662
		}
663
		try {
664
			format = params.get("format")[0];
665
		} catch (Exception e) {
666
			logMetacat.warn("pid not specified");
667
		} 
668
		// call the implementation
669
		boolean result = CNodeService.getInstance(request).reserveIdentifier(session, pid);
670
		OutputStream out = response.getOutputStream();
671
		response.setStatus(200);
672
		response.setContentType("text/xml");
673
		// nothing to send back
674
    }
675
    
676
    /**
677
     * 
678
     * @param id
679
     * @throws InvalidRequest
680
     * @throws InvalidToken
681
     * @throws ServiceFailure
682
     * @throws NotAuthorized
683
     * @throws NotFound
684
     * @throws NotImplemented
685
     * @throws IOException
686
     * @throws JiBXException 
687
     */
688
    private void resolve(String id) throws InvalidRequest, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
689
		Identifier pid = new Identifier();
690
		pid.setValue(id);
691
		ObjectLocationList locationList = CNodeService.getInstance(request).resolve(session, pid);
692
	    OutputStream out = response.getOutputStream();
693
		response.setStatus(200);
694
		response.setContentType("text/xml");
695
		TypeMarshaller.marshalTypeToOutputStream(locationList, out);
696
		
697
    }
698

    
699
    /**
700
     * Assert that a relationship exists between two resources
701
     * @param id
702
     * @return
703
     * @throws InvalidToken
704
     * @throws ServiceFailure
705
     * @throws NotAuthorized
706
     * @throws NotFound
707
     * @throws InvalidRequest
708
     * @throws NotImplemented
709
     */
710
    private boolean assertRelation(String id) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented {
711
		Identifier pidOfSubject = new Identifier();
712
		pidOfSubject.setValue(id);
713
		String relationship = null;
714
		try {
715
			relationship = params.get("relationship")[0];
716
		} catch (Exception e) {
717
			logMetacat.warn("relationship not specified");
718
		}
719
		Identifier pidOfObject = new Identifier();
720
		try {
721
			String objPid = params.get("pidOfObject")[0];
722
			pidOfObject.setValue(objPid);
723
		} catch (Exception e) {
724
			logMetacat.warn("pidOfObject not specified");
725
		}
726
		boolean result = CNodeService.getInstance(request).assertRelation(session, pidOfSubject, relationship, pidOfObject);
727
		response.setStatus(200);
728
		response.setContentType("text/xml");
729
		return result;
730
    }
731
    
732
    /**
733
     * Set the owner of a resource
734
     * @param id
735
     * @throws JiBXException
736
     * @throws InvalidToken
737
     * @throws ServiceFailure
738
     * @throws NotFound
739
     * @throws NotAuthorized
740
     * @throws NotImplemented
741
     * @throws InvalidRequest
742
     * @throws IOException
743
     * @throws IllegalAccessException 
744
     * @throws InstantiationException 
745
     */
746
    private void owner(String id) 
747
        throws JiBXException, InvalidToken, ServiceFailure, 
748
        NotFound, NotAuthorized, NotImplemented, InvalidRequest, IOException, 
749
        InstantiationException, IllegalAccessException {
750
		
751
        Identifier pid = new Identifier();
752
		    pid.setValue(id);
753

    
754
        long serialVersion = 0L;
755
        String serialVersionStr = null;
756
        
757
        // get the serialVersion
758
        try {
759
            serialVersionStr = params.get("serialVersion")[0];
760
            serialVersion = new Long(serialVersionStr).longValue();
761
            
762
        } catch (NullPointerException e) {
763
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
764
            logMetacat.error(msg);
765
            throw new InvalidRequest("4442", msg);
766
            
767
        }		    
768
		    
769
		    // get the subject
770
		    String subjectStr = params.get("subject")[0];
771
		    Subject subject = TypeMarshaller.unmarshalTypeFromStream(Subject.class, new ByteArrayInputStream(subjectStr.getBytes("UTF-8")));
772
		    
773
		    Identifier retPid = CNodeService.getInstance(request).setOwner(session, pid, subject, serialVersion);
774
		    OutputStream out = response.getOutputStream();
775
		    response.setStatus(200);
776
		    response.setContentType("text/xml");
777
		    TypeMarshaller.marshalTypeToOutputStream(retPid, out);		
778
    }
779
    
780
    /**
781
     * Processes the authorization check for given id
782
     * @param id
783
     * @return
784
     * @throws ServiceFailure
785
     * @throws InvalidToken
786
     * @throws NotFound
787
     * @throws NotAuthorized
788
     * @throws NotImplemented
789
     * @throws InvalidRequest
790
     */
791
    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
792
		Identifier pid = new Identifier();
793
		pid.setValue(id);
794
		String permission = params.get("action")[0];
795
		boolean result = CNodeService.getInstance(request).isAuthorized(session, pid, Permission.convert(permission));
796
		response.setStatus(200);
797
		response.setContentType("text/xml");
798
		return result;
799
    }
800
    
801
    /**
802
     * Register System Metadata without data or metadata object
803
     * @param pid identifier for System Metadata entry
804
     * @throws JiBXException 
805
     * @throws FileUploadException 
806
     * @throws IOException 
807
     * @throws InvalidRequest 
808
     * @throws ServiceFailure 
809
     * @throws InvalidSystemMetadata 
810
     * @throws NotAuthorized 
811
     * @throws NotImplemented 
812
     * @throws IllegalAccessException 
813
     * @throws InstantiationException 
814
     */
815
    protected Identifier registerSystemMetadata(String pid) throws ServiceFailure, InvalidRequest, IOException, FileUploadException, JiBXException, NotImplemented, NotAuthorized, InvalidSystemMetadata, InstantiationException, IllegalAccessException {
816
		logMetacat.debug("Entering registerSystemMetadata: " + pid);
817

    
818
		// get the system metadata from the request
819
		SystemMetadata systemMetadata = collectSystemMetadata();
820

    
821
		Identifier guid = new Identifier();
822
		guid.setValue(pid);
823
		logMetacat.debug("registering system metadata with pid " + guid.getValue());
824
		Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, guid, systemMetadata);
825
		
826
		response.setStatus(200);
827
		response.setContentType("text/xml");
828
		return retGuid;
829
			
830
	}
831
    
832
    /**
833
     * set the access perms on a document
834
     * @throws JiBXException 
835
     * @throws InvalidRequest 
836
     * @throws NotImplemented 
837
     * @throws NotAuthorized 
838
     * @throws NotFound 
839
     * @throws ServiceFailure 
840
     * @throws InvalidToken 
841
     * @throws IllegalAccessException 
842
     * @throws InstantiationException 
843
     * @throws IOException 
844
     * @throws SAXException 
845
     * @throws ParserConfigurationException 
846
     */
847
    protected void setAccess(String pid) 
848
        throws JiBXException, InvalidToken, ServiceFailure, NotFound, 
849
        NotAuthorized, NotImplemented, InvalidRequest, IOException, 
850
        InstantiationException, IllegalAccessException, ParserConfigurationException, 
851
        SAXException {
852

    
853
        long serialVersion = 0L;
854
        String serialVersionStr = null;
855
        
856
        // get the serialVersion
857
        try {
858
            serialVersionStr = params.get("serialVersion")[0];
859
            serialVersion = new Long(serialVersionStr).longValue();
860
            
861
        } catch (NullPointerException e) {
862
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
863
            logMetacat.error(msg);
864
            throw new InvalidRequest("4402", msg);
865
            
866
        }
867
        
868
        Identifier id = new Identifier();
869
        id.setValue(pid);
870
        
871
        AccessPolicy accessPolicy = collectAccessPolicy();
872
        CNodeService.getInstance(request).setAccessPolicy(session, id, accessPolicy, serialVersion);
873

    
874
    }
875
    
876
    /**
877
     *	Pass to the CN search service
878
     *
879
     * @throws NotImplemented 
880
     * @throws InvalidRequest 
881
     * @throws NotAuthorized 
882
     * @throws ServiceFailure 
883
     * @throws InvalidToken 
884
     * @throws Exception
885
     */
886
    private void query() 
887
        throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented {
888
        
889
    	  String query = null;
890
		    String queryType = null;
891
		    try {
892
		    	query = params.get("query")[0];
893
		    } catch (Exception e) {
894
		    	logMetacat.warn("query not specified");
895
		    }
896
		    try {
897
		    	String qt = params.get("queryType")[0];
898
		    	queryType = qt;
899
		    } catch (Exception e) {
900
		    	logMetacat.warn("queryType not specified");
901
		    }
902
		    
903
        	// expecting to throw NotImplemented
904
		    CNodeService.getInstance(request).search(session, queryType, query);
905
    }
906
    
907
    /**
908
     * Pass the request to get node replication authorization to CNodeService
909
     * 
910
     * @param pid  the identifier of the object to get authorization to replicate
911
     * 
912
     * @throws NotImplemented
913
     * @throws NotAuthorized
914
     * @throws InvalidToken
915
     * @throws ServiceFailure
916
     * @throws NotFound
917
     * @throws InvalidRequest
918
     */
919
    public boolean isNodeAuthorized(String pid) 
920
        throws NotImplemented, NotAuthorized, InvalidToken, ServiceFailure, 
921
        NotFound, InvalidRequest {
922
        
923
        boolean result = false;
924
        Subject targetNodeSubject = new Subject();
925
        String nodeSubject = null;
926
        Permission permission = null;
927
        String replPermission = null;
928
        
929
        // get the pid
930
        Identifier identifier = new Identifier();
931
        identifier.setValue(pid);
932
        
933
        // get the target node subject
934
        try {
935
            nodeSubject = params.get("targetNodeSubject")[0];
936
            targetNodeSubject.setValue(nodeSubject);
937
            
938
        } catch (NullPointerException e) {
939
            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
940
            logMetacat.error(msg);
941
            throw new InvalidRequest("4873", msg);
942
            
943
        }
944
        
945
        // get the permission
946
        try {
947
            replPermission = params.get("replicatePermission")[0];
948
            permission = Permission.convert(replPermission);
949

    
950
        } catch (NullPointerException e) {
951
            String msg = "The 'replicatePermission' must be provided as a parameter and was not.";
952
            logMetacat.error(msg);
953
            throw new InvalidRequest("4873", msg);
954

    
955
        }
956
        
957
        result =
958
            CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier, permission);
959
        
960
        response.setStatus(200);
961
        response.setContentType("text/xml");
962
        return result;
963
        
964
    }
965
    
966
    /**
967
     * Pass the request to set the replication policy to CNodeService
968
     * 
969
     * @param pid  the identifier of the object to set the replication policy on
970
     * 
971
     * @throws NotImplemented
972
     * @throws NotFound
973
     * @throws NotAuthorized
974
     * @throws ServiceFailure
975
     * @throws InvalidRequest
976
     * @throws InvalidToken
977
     * @throws IOException
978
     * @throws InstantiationException
979
     * @throws IllegalAccessException
980
     * @throws JiBXException
981
     */
982
    public boolean setReplicationPolicy(String pid) 
983
        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure, 
984
        InvalidRequest, InvalidToken, IOException, InstantiationException, 
985
        IllegalAccessException, JiBXException {
986
        
987
        boolean result = false;
988
        ReplicationPolicy policy = null;
989
        long serialVersion = 0L;
990
        String serialVersionStr = null;
991
       
992
        Identifier identifier = new Identifier();
993
        identifier.setValue(pid);
994
        
995
        // get the serialVersion
996
        try {
997
            serialVersionStr = multipartparams.get("serialVersion").get(0);
998
            serialVersion = new Long(serialVersionStr).longValue();
999
            
1000
        } catch (NullPointerException e) {
1001
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1002
            logMetacat.error(msg);
1003
            throw new InvalidRequest("4883", msg);
1004
            
1005
        }
1006
        policy = collectReplicationPolicy();
1007
        result = 
1008
            CNodeService.getInstance(request).setReplicationPolicy(session, identifier, policy, serialVersion);
1009
        response.setStatus(200);
1010
        response.setContentType("text/xml");
1011
        return result;
1012
        
1013
    }
1014
    
1015
    /**
1016
     * Pass the request to set the replication status to CNodeService
1017
     * 
1018
     * @param pid  the identifier of the object to set the replication status on
1019
     * 
1020
     * @throws ServiceFailure
1021
     * @throws NotImplemented
1022
     * @throws InvalidToken
1023
     * @throws NotAuthorized
1024
     * @throws InvalidRequest
1025
     * @throws NotFound
1026
     */
1027
    public boolean setReplicationStatus(String pid) 
1028
        throws ServiceFailure, NotImplemented, InvalidToken, NotAuthorized, 
1029
        InvalidRequest, NotFound {
1030

    
1031
        boolean result = false;
1032
        Identifier identifier = new Identifier();
1033
        identifier.setValue(pid);
1034
        long serialVersion = 0L;
1035
        String serialVersionStr = null;
1036
        ReplicationStatus status = null;
1037
        String replicationStatus = null;
1038
        NodeReference targetNodeRef = null;
1039
        String targetNode = null;
1040
        
1041
        // get the serialVersion
1042
        try {
1043
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1044
            serialVersion = new Long(serialVersionStr).longValue();
1045
            
1046
        } catch (NullPointerException e) {
1047
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1048
            logMetacat.error(msg);
1049
            throw new InvalidRequest("4730", msg);
1050
            
1051
        }
1052
        
1053
        // get the replication status param
1054
        try {
1055
            replicationStatus = multipartparams.get("replicationStatus").get(0);
1056
            status = ReplicationStatus.convert(replicationStatus);
1057
        } catch (Exception e) {
1058
            // TODO Auto-generated catch block
1059
            e.printStackTrace();
1060
        }
1061
        
1062
        // get the target node reference param
1063
        targetNode = multipartparams.get("nodeRef").get(0);
1064
        targetNodeRef = new NodeReference();
1065
        targetNodeRef.setValue(targetNode);
1066
        
1067
        result = 
1068
            CNodeService.getInstance(request).setReplicationStatus(session, identifier, targetNodeRef, status, serialVersion);       
1069
        response.setStatus(200);
1070
        response.setContentType("text/xml");
1071
        return result;
1072
        
1073
    }
1074
    
1075
    /**
1076
     * Pass the request to update the replication metadata to CNodeService
1077
     * 
1078
     * @param pid  the identifier of the object to update the replication metadata on
1079
     * 
1080
     * @throws ServiceFailure
1081
     * @throws NotImplemented
1082
     * @throws InvalidToken
1083
     * @throws NotAuthorized
1084
     * @throws InvalidRequest
1085
     * @throws NotFound
1086
     */
1087
    public boolean updateReplicationMetadata(String pid) 
1088
        throws ServiceFailure, NotImplemented, InvalidToken, NotAuthorized, 
1089
        InvalidRequest, NotFound {
1090

    
1091
        boolean result = false;
1092
        long serialVersion = 0L;
1093
        String serialVersionStr = null;
1094
        Replica replica = null;
1095
        Identifier identifier = new Identifier();
1096
        identifier.setValue(pid);
1097

    
1098
        // get the serialVersion
1099
        try {
1100
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1101
            serialVersion = new Long(serialVersionStr).longValue();
1102
            
1103
        } catch (NullPointerException e) {
1104
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1105
            logMetacat.error(msg);
1106
            throw new InvalidRequest("4853", msg);
1107
            
1108
        }
1109

    
1110
        replica = collectReplicaMetadata();
1111
        result = 
1112
            CNodeService.getInstance(request).updateReplicationMetadata(session, identifier, replica, serialVersion);
1113
        response.setStatus(200);
1114
        response.setContentType("text/xml");
1115
        return result;
1116

    
1117
    }
1118

    
1119
}
(1-1/9)