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: 2012-02-07 16:53:22 -0800 (Tue, 07 Feb 2012) $'
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.Enumeration;
33
import java.util.Map;
34

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

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

    
81
import edu.ucsb.nceas.metacat.dataone.CNodeService;
82
import edu.ucsb.nceas.metacat.properties.PropertyService;
83
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
84

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

    
115
    /** CN-specific operations **/
116
    protected static final String RESOURCE_RESERVE = "reserve";
117
    protected static final String RESOURCE_FORMATS = "formats";
118
    protected static final String RESOURCE_RESOLVE = "resolve";
119
    protected static final String RESOURCE_OWNER = "owner";
120
    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
121
    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
122
    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
123
    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
124

    
125
    public CNResourceHandler(ServletContext servletContext,
126
            HttpServletRequest request, HttpServletResponse response) {
127
        super(servletContext, request, response);
128
        logMetacat = Logger.getLogger(CNResourceHandler.class);
129
    }
130

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

    
143
        try {
144

    
145
        	// only service requests if we have D1 configured
146
        	if (!isD1Enabled()) {
147
        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
148
                serializeException(se, response.getOutputStream());
149
                return;
150
        	}
151
        	
152
            // get the resource
153
            String resource = request.getPathInfo();
154
            resource = resource.substring(resource.indexOf("/") + 1);
155

    
156
            // for the rest of the resouce
157
            String extra = null;
158

    
159
            logMetacat.debug("handling verb " + httpVerb
160
                    + " request with resource '" + resource + "'");
161
            boolean status = false;
162

    
163
            if (resource != null) {
164

    
165
                if (resource.startsWith(RESOURCE_ACCESS_RULES)
166
                        && httpVerb == PUT) {
167
                    logMetacat.debug("Setting access policy");
168
                    // after the command
169
                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
170
                    setAccess(extra);
171
                    status = true;
172
                    logMetacat.debug("done setting access");
173

    
174
                } else if (resource.startsWith(RESOURCE_META)) {
175
                    logMetacat.debug("Using resource: " + RESOURCE_META);
176

    
177
                    // after the command
178
                    extra = parseTrailing(resource, RESOURCE_META);
179

    
180
                    // get
181
                    if (httpVerb == GET) {
182
                        getSystemMetadataObject(extra);
183
                        status = true;
184
                    }
185
                    // post to register system metadata
186
                    if (httpVerb == POST) {
187
                        registerSystemMetadata();
188
                        status = true;
189
                    }
190

    
191
                } else if (resource.startsWith(RESOURCE_RESERVE)) {
192
                    // reserve the ID (in params)
193
                    if (httpVerb == POST) {
194
                        reserve();
195
                        status = true;
196
                    }
197
                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
198

    
199
                    // after the command
200
                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
201

    
202
                    // resolve the object location
203
                    if (httpVerb == GET) {
204
                        resolve(extra);
205
                        status = true;
206
                    }
207
                } else if (resource.startsWith(RESOURCE_OWNER)) {
208

    
209
                    // after the command
210
                    extra = parseTrailing(resource, RESOURCE_OWNER);
211

    
212
                    // set the owner
213
                    if (httpVerb == PUT) {
214
                        owner(extra);
215
                        status = true;
216
                    }
217
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
218

    
219
                    // after the command
220
                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
221

    
222
                    // authorized?
223
                    if (httpVerb == GET) {
224
                        isAuthorized(extra);
225
                        status = true;
226
                    }
227
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
228
                    logMetacat.debug("Using resource 'object'");
229
                    logMetacat
230
                            .debug("D1 Rest: Starting resource processing...");
231

    
232
                    // after the command
233
                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
234

    
235
                    logMetacat.debug("objectId: " + extra);
236
                    logMetacat.debug("verb:" + httpVerb);
237

    
238
                    if (httpVerb == GET) {
239
                        if (extra != null) {
240
                            getObject(extra);
241
                        } else {
242
                            listObjects();
243
                        }
244
                        status = true;
245
                    } else if (httpVerb == POST) {
246
                        putObject(FUNCTION_NAME_INSERT);
247
                        status = true;
248
                    } else if (httpVerb == HEAD) {
249
                        describeObject(extra);
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: "
297
                            + RESOURCE_REPLICATION_POLICY);
298
                    // get the trailing pid
299
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
300
                    setReplicationPolicy(extra);
301
                    status = true;
302

    
303
                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
304
                        && httpVerb == PUT) {
305

    
306
                    logMetacat.debug("Using resource: "
307
                            + RESOURCE_REPLICATION_META);
308
                    // get the trailing pid
309
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
310
                    updateReplicationMetadata(extra);
311
                    status = true;
312

    
313
                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
314
                        && httpVerb == PUT) {
315

    
316
                    logMetacat.debug("Using resource: "
317
                            + RESOURCE_REPLICATION_NOTIFY);
318
                    // get the trailing pid
319
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
320
                    setReplicationStatus(extra);
321
                    status = true;
322

    
323
                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
324
                        && httpVerb == GET) {
325

    
326
                    logMetacat.debug("Using resource: "
327
                            + RESOURCE_REPLICATION_AUTHORIZED);
328
                    // get the trailing pid
329
                    extra = parseTrailing(resource,
330
                            RESOURCE_REPLICATION_AUTHORIZED);
331
                    isNodeAuthorized(extra);
332
                    status = true;
333

    
334
                } else if (resource.startsWith(Constants.RESOURCE_MONITOR_PING)) {
335
                    if (httpVerb == GET) {
336
                    	// after the command
337
                        extra = parseTrailing(resource, Constants.RESOURCE_MONITOR_PING);
338
                        
339
                        logMetacat.debug("processing ping request");
340
                        Date result = CNodeService.getInstance(request).ping();
341
                        // TODO: send to output	
342
                        status = true;
343
                    }
344
                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
345
                    if (httpVerb == GET) {
346
                        listChecksumAlgorithms();
347
                        status = true;
348
                    }
349
                } else if (resource.startsWith(Constants.RESOURCE_META_OBSOLETEDBY)
350
                        && httpVerb == PUT) {
351

    
352
                    logMetacat.debug("Using resource: "
353
                            + Constants.RESOURCE_META_OBSOLETEDBY);
354
                    // get the trailing pid
355
                    extra = parseTrailing(resource, Constants.RESOURCE_META_OBSOLETEDBY);
356
                    setObsoletedBy(extra);
357
                    status = true;
358
                } else if (resource.startsWith(Constants.RESOURCE_REPLICATION_DELETE_REPLICA)
359
                        && httpVerb == PUT) {
360

    
361
                    logMetacat.debug("Using resource: "
362
                            + Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
363
                    // get the trailing pid
364
                    extra = parseTrailing(resource, Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
365
                    setObsoletedBy(extra);
366
                    status = true;
367
                }
368

    
369
                if (!status) {
370
                    throw new ServiceFailure("0000", "Unknown error, status = "
371
                            + status);
372
                }
373
            } else {
374
                throw new InvalidRequest("0000", "No resource matched for "
375
                        + resource);
376
            }
377
        } catch (BaseException be) {
378
            // report Exceptions as clearly and generically as possible
379
            OutputStream out = null;
380
            try {
381
                out = response.getOutputStream();
382
            } catch (IOException ioe) {
383
                logMetacat.error("Could not get output stream from response",
384
                        ioe);
385
            }
386
            serializeException(be, out);
387
        } catch (Exception e) {
388
            // report Exceptions as clearly and generically as possible
389
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
390
            OutputStream out = null;
391
            try {
392
                out = response.getOutputStream();
393
            } catch (IOException ioe) {
394
                logMetacat.error("Could not get output stream from response",
395
                        ioe);
396
            }
397
            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
398
            serializeException(se, out);
399
        }
400
    }
401

    
402
    /**
403
     * Get the checksum for the given guid
404
     * 
405
     * @param guid
406
     * @throws NotImplemented
407
     * @throws InvalidRequest
408
     * @throws NotFound
409
     * @throws NotAuthorized
410
     * @throws ServiceFailure
411
     * @throws InvalidToken
412
     * @throws IOException
413
     * @throws JiBXException
414
     */
415
    private void checksum(String guid) throws InvalidToken, ServiceFailure,
416
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
417
            JiBXException, IOException {
418
        Identifier guidid = new Identifier();
419
        guidid.setValue(guid);
420
        logMetacat.debug("getting checksum for object " + guid);
421
        Checksum c = CNodeService.getInstance(request).getChecksum(session,
422
                guidid);
423
        logMetacat.debug("got checksum " + c.getValue());
424
        response.setStatus(200);
425
        logMetacat.debug("serializing response");
426
        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
427
        logMetacat.debug("done serializing response.");
428

    
429
    }
430

    
431
    /**
432
     * get the logs based on passed params. Available params are token,
433
     * fromDate, toDate, event. See
434
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
435
     * .html#MN_crud.getLogRecords for more info
436
     * 
437
     * @throws NotImplemented
438
     * @throws InvalidRequest
439
     * @throws NotAuthorized
440
     * @throws ServiceFailure
441
     * @throws InvalidToken
442
     * @throws IOException
443
     * @throws JiBXException
444
     */
445
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
446
            InvalidRequest, NotImplemented, IOException, JiBXException {
447

    
448
        Date fromDate = null;
449
        Date toDate = null;
450
        Event event = null;
451
        Integer start = null;
452
        Integer count = null;
453

    
454
        try {
455
            String fromDateS = params.get("fromDate")[0];
456
            logMetacat.debug("param fromDateS: " + fromDateS);
457
            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
458
        } catch (Exception e) {
459
            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
460
        }
461
        try {
462
            String toDateS = params.get("toDate")[0];
463
            logMetacat.debug("param toDateS: " + toDateS);
464
            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
465
        } catch (Exception e) {
466
            logMetacat.warn("Could not parse toDate: " + e.getMessage());
467
        }
468
        try {
469
            String eventS = params.get("event")[0];
470
            event = Event.convert(eventS);
471
        } catch (Exception e) {
472
            logMetacat.warn("Could not parse event: " + e.getMessage());
473
        }
474
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
475

    
476
        try {
477
            start = Integer.parseInt(params.get("start")[0]);
478
        } catch (Exception e) {
479
            logMetacat.warn("Could not parse start: " + e.getMessage());
480
        }
481
        try {
482
            count = Integer.parseInt(params.get("count")[0]);
483
        } catch (Exception e) {
484
            logMetacat.warn("Could not parse count: " + e.getMessage());
485
        }
486

    
487
        logMetacat.debug("calling getLogRecords");
488
        Log log = CNodeService.getInstance(request).getLogRecords(session,
489
                fromDate, toDate, event, start, count);
490

    
491
        OutputStream out = response.getOutputStream();
492
        response.setStatus(200);
493
        response.setContentType("text/xml");
494

    
495
        TypeMarshaller.marshalTypeToOutputStream(log, out);
496

    
497
    }
498

    
499
    /**
500
     * Implements REST version of DataONE CRUD API --> get
501
     * 
502
     * @param guid
503
     *            ID of data object to be read
504
     * @throws NotImplemented
505
     * @throws InvalidRequest
506
     * @throws NotFound
507
     * @throws NotAuthorized
508
     * @throws ServiceFailure
509
     * @throws InvalidToken
510
     * @throws IOException
511
     */
512
    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
513
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
514
            IOException {
515

    
516
        Identifier id = new Identifier();
517
        id.setValue(guid);
518

    
519
        SystemMetadata sm = CNodeService.getInstance(request)
520
                .getSystemMetadata(session, id);
521

    
522
        // set the content type
523
        if (sm.getFormatId()
524
                .getValue()
525
                .trim()
526
                .equals(ObjectFormatCache.getInstance().getFormat("text/csv")
527
                        .getFormatId().getValue())) {
528
            response.setContentType("text/csv");
529
            response.setHeader("Content-Disposition",
530
                    "inline; filename=" + id.getValue() + ".csv");
531
        } else if (sm
532
                .getFormatId()
533
                .getValue()
534
                .trim()
535
                .equals(ObjectFormatCache.getInstance().getFormat("text/plain")
536
                        .getFormatId().getValue())) {
537
            response.setContentType("text/plain");
538
            response.setHeader("Content-Disposition",
539
                    "inline; filename=" + id.getValue() + ".txt");
540
        } else if (sm
541
                .getFormatId()
542
                .getValue()
543
                .trim()
544
                .equals(ObjectFormatCache.getInstance()
545
                        .getFormat("application/octet-stream").getFormatId()
546
                        .getValue())) {
547
            response.setContentType("application/octet-stream");
548
        } else {
549
            response.setContentType("text/xml");
550
            response.setHeader("Content-Disposition",
551
                    "inline; filename=" + id.getValue() + ".xml");
552
        }
553

    
554
        InputStream data = CNodeService.getInstance(request).get(session, id);
555

    
556
        OutputStream out = response.getOutputStream();
557
        response.setStatus(200);
558
        IOUtils.copyLarge(data, out);
559

    
560
    }
561

    
562
    /**
563
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
564
     * 
565
     * @param guid
566
     *            ID of data object to be read
567
     * @throws NotImplemented
568
     * @throws InvalidRequest
569
     * @throws NotFound
570
     * @throws NotAuthorized
571
     * @throws ServiceFailure
572
     * @throws InvalidToken
573
     * @throws IOException
574
     * @throws JiBXException
575
     */
576
    protected void getSystemMetadataObject(String guid) throws InvalidToken,
577
            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
578
            NotImplemented, IOException, JiBXException {
579

    
580
        Identifier id = new Identifier();
581
        id.setValue(guid);
582
        SystemMetadata sysmeta = CNodeService.getInstance(request)
583
                .getSystemMetadata(session, id);
584

    
585
        response.setContentType("text/xml");
586
        response.setStatus(200);
587
        OutputStream out = response.getOutputStream();
588

    
589
        // Serialize and write it to the output stream
590
        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
591
    }
592

    
593
    /**
594
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
595
     * handleInsertOrUpdateAction
596
     * 
597
     * @param guid
598
     *            - ID of data object to be inserted or updated. If action is
599
     *            update, the pid is the existing pid. If insert, the pid is the
600
     *            new one
601
     * @throws InvalidRequest
602
     * @throws ServiceFailure
603
     * @throws IdentifierNotUnique
604
     * @throws JiBXException
605
     * @throws NotImplemented
606
     * @throws InvalidSystemMetadata
607
     * @throws InsufficientResources
608
     * @throws UnsupportedType
609
     * @throws NotAuthorized
610
     * @throws InvalidToken
611
     * @throws IOException
612
     * @throws IllegalAccessException
613
     * @throws InstantiationException
614
     */
615
    protected void putObject(String action) throws ServiceFailure,
616
            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
617
            NotAuthorized, UnsupportedType, InsufficientResources,
618
            InvalidSystemMetadata, NotImplemented, IOException,
619
            InstantiationException, IllegalAccessException {
620
    	
621
        // Read the incoming data from its Mime Multipart encoding
622
        Map<String, File> files = collectMultipartFiles();
623
        
624
	    // get the encoded pid string from the body and make the object
625
        String pidString = multipartparams.get("pid").get(0);
626
        Identifier pid = new Identifier();
627
        pid.setValue(pidString);
628
        
629
        logMetacat.debug("putObject: " + pid.getValue() + "/" + action);
630
        
631
        InputStream object = null;
632
        InputStream sysmeta = null;
633

    
634
        File smFile = files.get("sysmeta");
635
        sysmeta = new FileInputStream(smFile);
636
        File objFile = files.get("object");
637
        object = new FileInputStream(objFile);
638

    
639
        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
640

    
641
            logMetacat.debug("Commence creation...");
642
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
643
                    SystemMetadata.class, sysmeta);
644

    
645
           
646
            logMetacat.debug("creating object with pid " + pid.getValue());
647
            Identifier rId = CNodeService.getInstance(request).create(session, pid, object, smd);
648

    
649
            OutputStream out = response.getOutputStream();
650
            response.setStatus(200);
651
            response.setContentType("text/xml");
652

    
653
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
654

    
655
        } else {
656
            throw new InvalidRequest("1000", "Operation must be create.");
657
        }
658
    }
659

    
660
    /**
661
     * List the object formats registered with the system
662
     * 
663
     * @throws NotImplemented
664
     * @throws InsufficientResources
665
     * @throws NotFound
666
     * @throws ServiceFailure
667
     * @throws InvalidRequest
668
     * @throws IOException
669
     * @throws JiBXException
670
     */
671
    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
672
            InsufficientResources, NotImplemented, IOException, JiBXException {
673
        logMetacat.debug("Entering listFormats()");
674

    
675
        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
676
                .listFormats();
677
        // get the response output stream
678
        OutputStream out = response.getOutputStream();
679
        response.setStatus(200);
680
        response.setContentType("text/xml");
681

    
682
        // style the object with a processing directive
683
        String stylesheet = null;
684
        try {
685
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
686
        } catch (PropertyNotFoundException e) {
687
            logMetacat.warn("Could not locate DataONE types XSLT: "
688
                    + e.getMessage());
689
        }
690

    
691
        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
692
                stylesheet);
693

    
694
    }
695
    
696
    private void listChecksumAlgorithms() throws IOException, ServiceFailure,
697
			NotImplemented, JiBXException {
698
		logMetacat.debug("Entering listFormats()");
699

    
700
		ChecksumAlgorithmList result = CNodeService.getInstance(request).listChecksumAlgorithms();
701

    
702
		// get the response output stream
703
		OutputStream out = response.getOutputStream();
704
		response.setStatus(200);
705
		response.setContentType("text/xml");
706

    
707
		// style the object with a processing directive
708
		String stylesheet = null;
709
		try {
710
			stylesheet = PropertyService.getProperty("dataone.types.xsl");
711
		} catch (PropertyNotFoundException e) {
712
			logMetacat.warn("Could not locate DataONE types XSLT: "
713
					+ e.getMessage());
714
		}
715

    
716
		TypeMarshaller.marshalTypeToOutputStream(result, out, stylesheet);
717

    
718
	}
719
    
720
    /**
721
     * http://mule1.dataone.org/ArchitectureDocs-current/apis/CN_APIs.html#CNRead.describe
722
     * @param pid
723
     * @throws InvalidToken
724
     * @throws ServiceFailure
725
     * @throws NotAuthorized
726
     * @throws NotFound
727
     * @throws NotImplemented
728
     * @throws InvalidRequest
729
     */
730
    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
731
    {
732
        response.setStatus(200);
733
        response.setContentType("text/xml");
734
        
735
        Identifier id = new Identifier();
736
        id.setValue(pid);
737

    
738
        DescribeResponse dr = CNodeService.getInstance(request).describe(session, id);
739
        //response.addHeader("pid", pid);
740
        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
741
        response.addHeader("Content-Length", dr.getContent_Length() + "");
742
        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
743
        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
744
        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
745

    
746
    }
747

    
748
    /**
749
     * Return the requested object format
750
     * 
751
     * @param fmtidStr
752
     *            the requested format identifier as a string
753
     * @throws NotImplemented
754
     * @throws InsufficientResources
755
     * @throws NotFound
756
     * @throws ServiceFailure
757
     * @throws InvalidRequest
758
     * @throws IOException
759
     * @throws JiBXException
760
     */
761
    private void getFormat(String fmtidStr) throws InvalidRequest,
762
            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
763
            IOException, JiBXException {
764
        logMetacat.debug("Entering listFormats()");
765

    
766
        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
767
        fmtid.setValue(fmtidStr);
768

    
769
        // get the specified object format
770
        ObjectFormat objectFormat = CNodeService.getInstance(request)
771
                .getFormat(fmtid);
772

    
773
        OutputStream out = response.getOutputStream();
774
        response.setStatus(200);
775
        response.setContentType("text/xml");
776

    
777
        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
778

    
779
    }
780

    
781
    /**
782
     * Reserve the given Identifier
783
     * 
784
     * @throws InvalidToken
785
     * @throws ServiceFailure
786
     * @throws NotAuthorized
787
     * @throws IdentifierNotUnique
788
     * @throws NotImplemented
789
     * @throws InvalidRequest
790
     * @throws IOException
791
     * @throws JiBXException
792
     */
793
    private void reserve() throws InvalidToken, ServiceFailure, NotAuthorized,
794
            IdentifierNotUnique, NotImplemented, InvalidRequest, IOException,
795
            JiBXException {
796
        Identifier pid = null;
797
        String scope = null;
798
        String format = null;
799
        // gather the params
800
        try {
801
            String id = params.get("pid")[0];
802
            pid = new Identifier();
803
            pid.setValue(id);
804
        } catch (Exception e) {
805
            logMetacat.warn("pid not specified");
806
        }
807
        try {
808
            scope = params.get("scope")[0];
809
        } catch (Exception e) {
810
            logMetacat.warn("pid not specified");
811
        }
812
        try {
813
            format = params.get("format")[0];
814
        } catch (Exception e) {
815
            logMetacat.warn("pid not specified");
816
        }
817
        // call the implementation
818
        Identifier resultPid = CNodeService.getInstance(request)
819
                .reserveIdentifier(session, pid);
820
        OutputStream out = response.getOutputStream();
821
        response.setStatus(200);
822
        response.setContentType("text/xml");
823
        // send back the reserved pid
824
        TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
825
    }
826

    
827
    /**
828
     * 
829
     * @param id
830
     * @throws InvalidRequest
831
     * @throws InvalidToken
832
     * @throws ServiceFailure
833
     * @throws NotAuthorized
834
     * @throws NotFound
835
     * @throws NotImplemented
836
     * @throws IOException
837
     * @throws JiBXException
838
     */
839
    private void resolve(String id) throws InvalidRequest, InvalidToken,
840
            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
841
            IOException, JiBXException {
842
        Identifier pid = new Identifier();
843
        pid.setValue(id);
844
        ObjectLocationList locationList = CNodeService.getInstance(request)
845
                .resolve(session, pid);
846
        OutputStream out = response.getOutputStream();
847
        response.setStatus(200);
848
        response.setContentType("text/xml");
849
        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
850

    
851
    }
852

    
853
    /**
854
     * Set the owner of a resource
855
     * 
856
     * @param id
857
     * @throws JiBXException
858
     * @throws InvalidToken
859
     * @throws ServiceFailure
860
     * @throws NotFound
861
     * @throws NotAuthorized
862
     * @throws NotImplemented
863
     * @throws InvalidRequest
864
     * @throws IOException
865
     * @throws IllegalAccessException
866
     * @throws InstantiationException
867
     * @throws VersionMismatch 
868
     */
869
    private void owner(String id) throws JiBXException, InvalidToken,
870
            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
871
            InvalidRequest, IOException, InstantiationException,
872
            IllegalAccessException, VersionMismatch {
873

    
874
        Identifier pid = new Identifier();
875
        pid.setValue(id);
876

    
877
        long serialVersion = 0L;
878
        String serialVersionStr = null;
879

    
880
        // get the serialVersion
881
        try {
882
            serialVersionStr = params.get("serialVersion")[0];
883
            serialVersion = new Long(serialVersionStr).longValue();
884

    
885
        } catch (NullPointerException e) {
886
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
887
            logMetacat.error(msg);
888
            throw new InvalidRequest("4442", msg);
889

    
890
        }
891

    
892
        // get the subject
893
        String subjectStr = params.get("subject")[0];
894
        Subject subject = TypeMarshaller.unmarshalTypeFromStream(Subject.class,
895
                new ByteArrayInputStream(subjectStr.getBytes("UTF-8")));
896

    
897
        Identifier retPid = CNodeService.getInstance(request).setRightsHolder(session, pid, subject, serialVersion);
898
        OutputStream out = response.getOutputStream();
899
        response.setStatus(200);
900
        response.setContentType("text/xml");
901
        TypeMarshaller.marshalTypeToOutputStream(retPid, out);
902
    }
903

    
904
    /**
905
     * Processes the authorization check for given id
906
     * 
907
     * @param id
908
     * @return
909
     * @throws ServiceFailure
910
     * @throws InvalidToken
911
     * @throws NotFound
912
     * @throws NotAuthorized
913
     * @throws NotImplemented
914
     * @throws InvalidRequest
915
     */
916
    private boolean isAuthorized(String id) throws ServiceFailure,
917
            InvalidToken, NotFound, NotAuthorized, NotImplemented,
918
            InvalidRequest {
919
        Identifier pid = new Identifier();
920
        pid.setValue(id);
921
        String permission = params.get("action")[0];
922
        boolean result = CNodeService.getInstance(request).isAuthorized(
923
                session, pid, Permission.convert(permission));
924
        response.setStatus(200);
925
        response.setContentType("text/xml");
926
        return result;
927
    }
928

    
929
    /**
930
     * Register System Metadata without data or metadata object
931
     * 
932
     * @param pid
933
     *            identifier for System Metadata entry
934
     * @throws JiBXException
935
     * @throws FileUploadException
936
     * @throws IOException
937
     * @throws InvalidRequest
938
     * @throws ServiceFailure
939
     * @throws InvalidSystemMetadata
940
     * @throws NotAuthorized
941
     * @throws NotImplemented
942
     * @throws IllegalAccessException
943
     * @throws InstantiationException
944
     */
945
    protected void registerSystemMetadata()
946
            throws ServiceFailure, InvalidRequest, IOException,
947
            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
948
            InvalidSystemMetadata, InstantiationException,
949
            IllegalAccessException {
950
    	
951
    	// Read the incoming data from its Mime Multipart encoding
952
        Map<String, File> files = collectMultipartFiles();
953
        
954
    	// get the encoded pid string from the body and make the object
955
        String pidString = multipartparams.get("pid").get(0);
956
        Identifier pid = new Identifier();
957
        pid.setValue(pidString);
958
        
959
        logMetacat.debug("registerSystemMetadata: " + pid);
960

    
961
        // get the system metadata from the request
962
        File smFile = files.get("sysmeta");
963
        FileInputStream sysmeta = new FileInputStream(smFile);
964
        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
965

    
966
        logMetacat.debug("registering system metadata with pid " + pid.getValue());
967
        Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, systemMetadata);
968

    
969
        OutputStream out = response.getOutputStream();
970
        response.setStatus(200);
971
        response.setContentType("text/xml");
972
        
973
        TypeMarshaller.marshalTypeToOutputStream(retGuid, out);
974

    
975
    }
976

    
977
    /**
978
     * set the access perms on a document
979
     * 
980
     * @throws JiBXException
981
     * @throws InvalidRequest
982
     * @throws NotImplemented
983
     * @throws NotAuthorized
984
     * @throws NotFound
985
     * @throws ServiceFailure
986
     * @throws InvalidToken
987
     * @throws IllegalAccessException
988
     * @throws InstantiationException
989
     * @throws IOException
990
     * @throws SAXException
991
     * @throws ParserConfigurationException
992
     * @throws VersionMismatch 
993
     */
994
    protected void setAccess(String pid) throws JiBXException, InvalidToken,
995
            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
996
            InvalidRequest, IOException, InstantiationException,
997
            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
998

    
999
        long serialVersion = 0L;
1000
        String serialVersionStr = null;
1001

    
1002
        // get the serialVersion
1003
        try {
1004
            serialVersionStr = params.get("serialVersion")[0];
1005
            serialVersion = new Long(serialVersionStr).longValue();
1006

    
1007
        } catch (NullPointerException e) {
1008
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1009
            logMetacat.error(msg);
1010
            throw new InvalidRequest("4402", msg);
1011

    
1012
        }
1013

    
1014
        Identifier id = new Identifier();
1015
        id.setValue(pid);
1016

    
1017
        AccessPolicy accessPolicy = collectAccessPolicy();
1018
        CNodeService.getInstance(request).setAccessPolicy(session, id,
1019
                accessPolicy, serialVersion);
1020

    
1021
    }
1022

    
1023
    /**
1024
     * List the objects
1025
     * 
1026
     * @throws NotImplemented
1027
     * @throws InvalidRequest
1028
     * @throws NotAuthorized
1029
     * @throws ServiceFailure
1030
     * @throws InvalidToken
1031
     * @throws NotFound
1032
     * @throws IOException
1033
     * @throws JiBXException
1034
     * @throws Exception
1035
     */
1036
    private void listObjects() throws InvalidToken, ServiceFailure,
1037
            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
1038
            IOException, JiBXException {
1039

    
1040
        Date startTime = null;
1041
        Date endTime = null;
1042
        ObjectFormat objectFormat = null;
1043
        boolean replicaStatus = false;
1044
        int start = 0;
1045
        int count = -1;
1046
        Enumeration<String> paramlist = request.getParameterNames();
1047
        while (paramlist.hasMoreElements()) {
1048
            // parse the params and make the call
1049
            String name = paramlist.nextElement();
1050
            String[] value = request.getParameterValues(name);
1051

    
1052
            if (name.equals("startTime") && value != null) {
1053
                try {
1054
                    startTime = DateTimeMarshaller
1055
                            .deserializeDateToUTC(value[0]);
1056
                } catch (Exception e) {
1057
                    // if we can't parse it, just don't use the startTime param
1058
                    logMetacat.warn("Could not parse startTime: " + value[0]);
1059
                    startTime = null;
1060
                }
1061
            } else if (name.equals("endTime") && value != null) {
1062
                try {
1063
                    endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
1064
                } catch (Exception e) {
1065
                    // if we can't parse it, just don't use the endTime param
1066
                    logMetacat.warn("Could not parse endTime: " + value[0]);
1067
                    endTime = null;
1068
                }
1069
            } else if (name.equals("objectFormat") && value != null) {
1070
                objectFormat = ObjectFormatCache.getInstance().getFormat(
1071
                        value[0]);
1072
            } else if (name.equals("replicaStatus") && value != null) {
1073
                replicaStatus = Boolean.parseBoolean(value[0]);
1074
            } else if (name.equals("start") && value != null) {
1075
                start = Integer.valueOf(value[0]);
1076
            } else if (name.equals("count") && value != null) {
1077
                count = Integer.valueOf(value[0]);
1078
            }
1079
        }
1080
        // make the call
1081
        logMetacat.debug("session: " + session + " startTime: " + startTime
1082
                + " endtime: " + endTime + " objectFormat: " + objectFormat
1083
                + " replicaStatus: " + replicaStatus + " start: " + start
1084
                + " count: " + count);
1085

    
1086
        ObjectFormatIdentifier fmtid = null;
1087
        if (objectFormat != null) {
1088
            fmtid = objectFormat.getFormatId();
1089
        }
1090

    
1091
        // get the list
1092
        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
1093
                startTime, endTime, fmtid, replicaStatus, start, count);
1094

    
1095
        // send it
1096
        OutputStream out = response.getOutputStream();
1097
        response.setStatus(200);
1098
        response.setContentType("text/xml");
1099

    
1100
        // style the object with a processing directive
1101
        String stylesheet = null;
1102
        try {
1103
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
1104
        } catch (PropertyNotFoundException e) {
1105
            logMetacat.warn("Could not locate DataONE types XSLT: "
1106
                    + e.getMessage());
1107
        }
1108

    
1109
        // Serialize and write it to the output stream
1110
        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
1111
    }
1112

    
1113
    /**
1114
     * Pass the request to get node replication authorization to CNodeService
1115
     * 
1116
     * @param pid
1117
     *            the identifier of the object to get authorization to replicate
1118
     * 
1119
     * @throws NotImplemented
1120
     * @throws NotAuthorized
1121
     * @throws InvalidToken
1122
     * @throws ServiceFailure
1123
     * @throws NotFound
1124
     * @throws InvalidRequest
1125
     */
1126
    public boolean isNodeAuthorized(String pid) throws NotImplemented,
1127
            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
1128
            InvalidRequest {
1129

    
1130
        boolean result = false;
1131
        Subject targetNodeSubject = new Subject();
1132
        String nodeSubject = null;
1133
        String replPermission = null;
1134

    
1135
        // get the pid
1136
        Identifier identifier = new Identifier();
1137
        identifier.setValue(pid);
1138

    
1139
        // get the target node subject
1140
        try {
1141
            nodeSubject = params.get("targetNodeSubject")[0];
1142
            targetNodeSubject.setValue(nodeSubject);
1143

    
1144
        } catch (NullPointerException e) {
1145
            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
1146
            logMetacat.error(msg);
1147
            throw new InvalidRequest("4873", msg);
1148

    
1149
        }
1150

    
1151
        result = CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier);
1152

    
1153
        response.setStatus(200);
1154
        response.setContentType("text/xml");
1155
        return result;
1156

    
1157
    }
1158

    
1159
    /**
1160
     * Pass the request to set the replication policy to CNodeService
1161
     * 
1162
     * @param pid
1163
     *            the identifier of the object to set the replication policy on
1164
     * 
1165
     * @throws NotImplemented
1166
     * @throws NotFound
1167
     * @throws NotAuthorized
1168
     * @throws ServiceFailure
1169
     * @throws InvalidRequest
1170
     * @throws InvalidToken
1171
     * @throws IOException
1172
     * @throws InstantiationException
1173
     * @throws IllegalAccessException
1174
     * @throws JiBXException
1175
     * @throws VersionMismatch 
1176
     */
1177
    public boolean setReplicationPolicy(String pid) throws NotImplemented,
1178
            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
1179
            InvalidToken, IOException, InstantiationException,
1180
            IllegalAccessException, JiBXException, VersionMismatch {
1181

    
1182
        boolean result = false;
1183
        ReplicationPolicy policy = null;
1184
        long serialVersion = 0L;
1185
        String serialVersionStr = null;
1186

    
1187
        Identifier identifier = new Identifier();
1188
        identifier.setValue(pid);
1189

    
1190
        policy = collectReplicationPolicy();
1191

    
1192
        // get the serialVersion
1193
        try {
1194
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1195
            serialVersion = new Long(serialVersionStr).longValue();
1196

    
1197
        } catch (NullPointerException e) {
1198
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1199
            logMetacat.error(msg);
1200
            throw new InvalidRequest("4883", msg);
1201

    
1202
        }
1203
        result = CNodeService.getInstance(request).setReplicationPolicy(
1204
                session, identifier, policy, serialVersion);
1205
        response.setStatus(200);
1206
        response.setContentType("text/xml");
1207
        return result;
1208

    
1209
    }
1210
    
1211
    public boolean setObsoletedBy(String pid) throws NotImplemented,
1212
	    NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
1213
	    InvalidToken, IOException, InstantiationException,
1214
	    IllegalAccessException, JiBXException, VersionMismatch {
1215
	
1216
		boolean result = false;
1217
		long serialVersion = 0L;
1218
		String serialVersionStr = null;
1219
		
1220
		Identifier identifier = new Identifier();
1221
		identifier.setValue(pid);
1222
		
1223
		Identifier obsoletedByPid = null;
1224
		try {
1225
			String obsoletedByPidString = params.get("obsoletedByPid")[0];
1226
			obsoletedByPid = new Identifier();
1227
			obsoletedByPid.setValue(obsoletedByPidString);
1228
		} catch (NullPointerException e) {
1229
		    String msg = "The 'obsoletedByPid' must be provided as a parameter and was not.";
1230
		    logMetacat.error(msg);
1231
		    throw new InvalidRequest("4883", msg);
1232
		}
1233
		
1234
		// get the serialVersion
1235
		try {
1236
		    serialVersionStr = params.get("serialVersion")[0];
1237
		    serialVersion = new Long(serialVersionStr).longValue();
1238
		
1239
		} catch (NullPointerException e) {
1240
		    String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1241
		    logMetacat.error(msg);
1242
		    throw new InvalidRequest("4883", msg);
1243
		
1244
		}
1245
		result = CNodeService.getInstance(request).setObsoletedBy(
1246
		        session, identifier, obsoletedByPid, serialVersion);
1247
		response.setStatus(200);
1248
		response.setContentType("text/xml");
1249
		return result;
1250
	
1251
	}
1252
    
1253
    public boolean deleteReplica(String pid) throws NotImplemented, NotFound,
1254
			NotAuthorized, ServiceFailure, InvalidRequest, InvalidToken,
1255
			IOException, InstantiationException, IllegalAccessException,
1256
			JiBXException, VersionMismatch {
1257

    
1258
		boolean result = false;
1259
		long serialVersion = 0L;
1260
		String serialVersionStr = null;
1261

    
1262
		Identifier identifier = new Identifier();
1263
		identifier.setValue(pid);
1264

    
1265
		NodeReference nodeId = null;
1266
		try {
1267
			String nodeIdString = params.get("nodeId")[0];
1268
			nodeId = new NodeReference();
1269
			nodeId.setValue(nodeIdString);
1270
		} catch (NullPointerException e) {
1271
			String msg = "The 'nodeId' must be provided as a parameter and was not.";
1272
			logMetacat.error(msg);
1273
			throw new InvalidRequest("4883", msg);
1274
		}
1275

    
1276
		// get the serialVersion
1277
		try {
1278
			serialVersionStr = params.get("serialVersion")[0];
1279
			serialVersion = new Long(serialVersionStr).longValue();
1280

    
1281
		} catch (NullPointerException e) {
1282
			String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1283
			logMetacat.error(msg);
1284
			throw new InvalidRequest("4883", msg);
1285

    
1286
		}
1287
		result = CNodeService.getInstance(request).deleteReplicationMetadata(session, identifier, nodeId, serialVersion);
1288
		response.setStatus(200);
1289
		response.setContentType("text/xml");
1290
		return result;
1291

    
1292
	}
1293

    
1294
    /**
1295
     * Pass the request to set the replication status to CNodeService
1296
     * 
1297
     * @param pid
1298
     *            the identifier of the object to set the replication status on
1299
     * 
1300
     * @throws ServiceFailure
1301
     * @throws NotImplemented
1302
     * @throws InvalidToken
1303
     * @throws NotAuthorized
1304
     * @throws InvalidRequest
1305
     * @throws NotFound
1306
     * @throws JiBXException 
1307
     * @throws IllegalAccessException 
1308
     * @throws InstantiationException 
1309
     * @throws IOException 
1310
     */
1311
    public boolean setReplicationStatus(String pid) throws ServiceFailure,
1312
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1313
            NotFound {
1314
        
1315
        boolean result = false;
1316
        Identifier identifier = new Identifier();
1317
        identifier.setValue(pid);
1318
        BaseException failure = null;
1319
        ReplicationStatus status = null;
1320
        String replicationStatus = null;
1321
        NodeReference targetNodeRef = null;
1322
        String targetNode = null;
1323

    
1324
        // Parse the params out of the multipart form data
1325
        // Read the incoming data from its Mime Multipart encoding
1326
        logMetacat.debug("Parsing ReplicaStatus from the mime multipart entity");
1327

    
1328
        try {
1329
            failure = collectReplicationStatus();
1330
            
1331
        } catch (IOException e2) {
1332
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1333
                e2.getMessage());
1334
            
1335
        } catch (InstantiationException e2) {
1336
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1337
                e2.getMessage());
1338
            
1339
        } catch (IllegalAccessException e2) {
1340
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1341
                    e2.getMessage());
1342
            
1343
        } catch (JiBXException e2) {
1344
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1345
                    e2.getMessage());
1346
            
1347
        }
1348
        
1349
        // get the replication status param
1350
        try {
1351
            replicationStatus = multipartparams.get("status").get(0);
1352
            status = ReplicationStatus.convert(replicationStatus);
1353

    
1354
        } catch (NullPointerException npe) {
1355

    
1356
            logMetacat.debug("The 'status' parameter was not found in the "
1357
                    + "multipartparams map.  Trying the params map.");
1358

    
1359
            try {
1360
                replicationStatus = params.get("status")[0];
1361
                status = ReplicationStatus.convert(replicationStatus
1362
                        .toLowerCase());
1363

    
1364
            } catch (Exception e) {
1365
                String msg = "The 'status' must be provided as a parameter and was not.";
1366
                logMetacat.error(msg);
1367
                throw new InvalidRequest("4730", msg);
1368

    
1369
            }
1370

    
1371
        }
1372

    
1373
        // get the target node reference param
1374
        try {
1375
            targetNode = multipartparams.get("nodeRef").get(0);
1376
            targetNodeRef = new NodeReference();
1377
            targetNodeRef.setValue(targetNode);
1378

    
1379
        } catch (NullPointerException e) {
1380
            logMetacat.debug("The 'nodeRef' parameter was not found in the "
1381
                    + "multipartparams map.  Trying the params map.");
1382

    
1383
            try {
1384
                targetNode = params.get("nodeRef")[0];
1385
                targetNodeRef = new NodeReference();
1386
                targetNodeRef.setValue(targetNode);
1387

    
1388
            } catch (Exception e1) {
1389
                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
1390
                logMetacat.error(msg);
1391
                throw new InvalidRequest("4730", msg);
1392

    
1393
            }
1394

    
1395
        }
1396

    
1397
        result = CNodeService.getInstance(request).setReplicationStatus(
1398
                session, identifier, targetNodeRef, status, failure);
1399
        response.setStatus(200);
1400
        response.setContentType("text/xml");
1401
        return result;
1402

    
1403
    }
1404

    
1405
    /**
1406
     * Pass the request to update the replication metadata to CNodeService
1407
     * 
1408
     * @param pid
1409
     *            the identifier of the object to update the replication
1410
     *            metadata on
1411
     * 
1412
     * @throws ServiceFailure
1413
     * @throws NotImplemented
1414
     * @throws InvalidToken
1415
     * @throws NotAuthorized
1416
     * @throws InvalidRequest
1417
     * @throws NotFound
1418
     * @throws VersionMismatch 
1419
     */
1420
    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
1421
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1422
            NotFound, VersionMismatch {
1423

    
1424
        boolean result = false;
1425
        long serialVersion = 0L;
1426
        String serialVersionStr = null;
1427
        Replica replica = null;
1428
        Identifier identifier = new Identifier();
1429
        identifier.setValue(pid);
1430

    
1431
        replica = collectReplicaMetadata();
1432

    
1433
        // get the serialVersion
1434
        try {
1435
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1436
            serialVersion = new Long(serialVersionStr).longValue();
1437

    
1438
        } catch (NullPointerException e) {
1439
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1440
            logMetacat.error(msg);
1441
            throw new InvalidRequest("4853", msg);
1442

    
1443
        }
1444

    
1445
        result = CNodeService.getInstance(request).updateReplicationMetadata(
1446
                session, identifier, replica, serialVersion);
1447
        response.setStatus(200);
1448
        response.setContentType("text/xml");
1449
        return result;
1450

    
1451
    }
1452

    
1453
}
(1-1/9)