Project

General

Profile

1 6253 leinfelder
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2011 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author$'
7
 *     '$Date$'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.restservice;
24
25
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.IOException;
28
import java.io.InputStream;
29
import java.io.OutputStream;
30
import java.util.Date;
31 6622 leinfelder
import java.util.Enumeration;
32 6253 leinfelder
import java.util.Map;
33
34
import javax.servlet.ServletContext;
35
import javax.servlet.http.HttpServletRequest;
36
import javax.servlet.http.HttpServletResponse;
37 6514 leinfelder
import javax.xml.parsers.ParserConfigurationException;
38 6253 leinfelder
39 6269 leinfelder
import org.apache.commons.fileupload.FileUploadException;
40 6253 leinfelder
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 6869 cjones
import org.dataone.service.exceptions.VersionMismatch;
55 6366 leinfelder
import org.dataone.service.types.v1.AccessPolicy;
56
import org.dataone.service.types.v1.Checksum;
57 6803 leinfelder
import org.dataone.service.types.v1.ChecksumAlgorithmList;
58
import org.dataone.service.types.v1.DescribeResponse;
59 6366 leinfelder
import org.dataone.service.types.v1.Event;
60
import org.dataone.service.types.v1.Identifier;
61
import org.dataone.service.types.v1.Log;
62 6592 cjones
import org.dataone.service.types.v1.NodeReference;
63 6366 leinfelder
import org.dataone.service.types.v1.ObjectFormat;
64
import org.dataone.service.types.v1.ObjectFormatIdentifier;
65
import org.dataone.service.types.v1.ObjectFormatList;
66 6622 leinfelder
import org.dataone.service.types.v1.ObjectList;
67 6366 leinfelder
import org.dataone.service.types.v1.ObjectLocationList;
68
import org.dataone.service.types.v1.Permission;
69 6592 cjones
import org.dataone.service.types.v1.Replica;
70
import org.dataone.service.types.v1.ReplicationPolicy;
71
import org.dataone.service.types.v1.ReplicationStatus;
72 6366 leinfelder
import org.dataone.service.types.v1.Subject;
73
import org.dataone.service.types.v1.SystemMetadata;
74 6803 leinfelder
import org.dataone.service.util.Constants;
75 6469 leinfelder
import org.dataone.service.util.DateTimeMarshaller;
76 7048 leinfelder
import org.dataone.service.util.EncodingUtilities;
77 6367 leinfelder
import org.dataone.service.util.TypeMarshaller;
78 6253 leinfelder
import org.jibx.runtime.JiBXException;
79 6514 leinfelder
import org.xml.sax.SAXException;
80 6253 leinfelder
81
import edu.ucsb.nceas.metacat.dataone.CNodeService;
82 6639 leinfelder
import edu.ucsb.nceas.metacat.properties.PropertyService;
83
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
84 6253 leinfelder
85
/**
86
 * CN REST service implementation handler
87
 *
88 6756 cjones
 * ****************** 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 6253 leinfelder
 * @author leinfelder
111 6756 cjones
 *
112 6253 leinfelder
 */
113 6267 leinfelder
public class CNResourceHandler extends D1ResourceHandler {
114 6253 leinfelder
115 6756 cjones
    /** CN-specific operations **/
116 6253 leinfelder
    protected static final String RESOURCE_RESERVE = "reserve";
117 6271 leinfelder
    protected static final String RESOURCE_FORMATS = "formats";
118 6253 leinfelder
    protected static final String RESOURCE_RESOLVE = "resolve";
119
    protected static final String RESOURCE_OWNER = "owner";
120 6592 cjones
    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 6756 cjones
125 6253 leinfelder
    public CNResourceHandler(ServletContext servletContext,
126 6756 cjones
            HttpServletRequest request, HttpServletResponse response) {
127
        super(servletContext, request, response);
128 6253 leinfelder
        logMetacat = Logger.getLogger(CNResourceHandler.class);
129 6756 cjones
    }
130 6253 leinfelder
131 6756 cjones
    /**
132
     * This function is called from REST API servlet and handles each request to
133
     * the servlet
134 6253 leinfelder
     *
135 6756 cjones
     * @param httpVerb
136
     *            (GET, POST, PUT or DELETE)
137 6253 leinfelder
     */
138 6271 leinfelder
    @Override
139 6253 leinfelder
    public void handle(byte httpVerb) {
140 6756 cjones
        // prepare the handler
141
        super.handle(httpVerb);
142
143 6253 leinfelder
        try {
144 6282 leinfelder
145 6994 leinfelder
        	// 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 6756 cjones
            // get the resource
153 6282 leinfelder
            String resource = request.getPathInfo();
154
            resource = resource.substring(resource.indexOf("/") + 1);
155 6756 cjones
156 6396 leinfelder
            // for the rest of the resouce
157 6282 leinfelder
            String extra = null;
158 6756 cjones
159
            logMetacat.debug("handling verb " + httpVerb
160
                    + " request with resource '" + resource + "'");
161 6253 leinfelder
            boolean status = false;
162 6271 leinfelder
163 6253 leinfelder
            if (resource != null) {
164
165 6756 cjones
                if (resource.startsWith(RESOURCE_ACCESS_RULES)
166
                        && httpVerb == PUT) {
167 6253 leinfelder
                    logMetacat.debug("Setting access policy");
168 6514 leinfelder
                    // after the command
169
                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
170
                    setAccess(extra);
171 6253 leinfelder
                    status = true;
172
                    logMetacat.debug("done setting access");
173 6756 cjones
174 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_META)) {
175 6253 leinfelder
                    logMetacat.debug("Using resource: " + RESOURCE_META);
176 6756 cjones
177 6396 leinfelder
                    // after the command
178
                    extra = parseTrailing(resource, RESOURCE_META);
179 6756 cjones
180 6253 leinfelder
                    // get
181
                    if (httpVerb == GET) {
182 6282 leinfelder
                        getSystemMetadataObject(extra);
183 6253 leinfelder
                        status = true;
184
                    }
185
                    // post to register system metadata
186
                    if (httpVerb == POST) {
187 6974 leinfelder
                        registerSystemMetadata();
188 6756 cjones
                        status = true;
189 6253 leinfelder
                    }
190
191 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_RESERVE)) {
192 6253 leinfelder
                    // reserve the ID (in params)
193
                    if (httpVerb == POST) {
194 6756 cjones
                        reserve();
195
                        status = true;
196 6253 leinfelder
                    }
197 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
198 6756 cjones
199
                    // after the command
200 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
201 6756 cjones
202 6253 leinfelder
                    // resolve the object location
203
                    if (httpVerb == GET) {
204 6756 cjones
                        resolve(extra);
205
                        status = true;
206 6253 leinfelder
                    }
207 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_OWNER)) {
208 6756 cjones
209
                    // after the command
210 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_OWNER);
211 6756 cjones
212 6253 leinfelder
                    // set the owner
213
                    if (httpVerb == PUT) {
214 6756 cjones
                        owner(extra);
215
                        status = true;
216
                    }
217 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
218 6756 cjones
219
                    // after the command
220 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
221 6756 cjones
222 6253 leinfelder
                    // authorized?
223
                    if (httpVerb == GET) {
224 6756 cjones
                        isAuthorized(extra);
225
                        status = true;
226
                    }
227 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
228 6253 leinfelder
                    logMetacat.debug("Using resource 'object'");
229 6756 cjones
                    logMetacat
230
                            .debug("D1 Rest: Starting resource processing...");
231
232 6396 leinfelder
                    // after the command
233
                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
234 6756 cjones
235 6282 leinfelder
                    logMetacat.debug("objectId: " + extra);
236 6253 leinfelder
                    logMetacat.debug("verb:" + httpVerb);
237
238
                    if (httpVerb == GET) {
239 6756 cjones
                        if (extra != null) {
240
                            getObject(extra);
241
                        } else {
242
                            listObjects();
243
                        }
244 6253 leinfelder
                        status = true;
245
                    } else if (httpVerb == POST) {
246 6973 leinfelder
                        putObject(FUNCTION_NAME_INSERT);
247 6253 leinfelder
                        status = true;
248 6803 leinfelder
                    } else if (httpVerb == HEAD) {
249
                        describeObject(extra);
250
                        status = true;
251 7077 leinfelder
                    } else if (httpVerb == DELETE) {
252
                        deleteObject(extra);
253
                        status = true;
254
                    }
255 6756 cjones
256 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_FORMATS)) {
257 6756 cjones
                    logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
258
259
                    // after the command
260
                    extra = parseTrailing(resource, RESOURCE_FORMATS);
261
262
                    // handle each verb
263
                    if (httpVerb == GET) {
264
                        if (extra == null) {
265
                            // list the formats collection
266
                            listFormats();
267
                        } else {
268
                            // get the specified format
269
                            getFormat(extra);
270
                        }
271
                        status = true;
272
                    }
273
274 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_LOG)) {
275 6253 leinfelder
                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
276 6756 cjones
                    // handle log events
277 6253 leinfelder
                    if (httpVerb == GET) {
278
                        getLog();
279
                        status = true;
280
                    }
281
282 7155 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
283
                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
284
                    // handle archive events
285
                    if (httpVerb == PUT) {
286
                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
287
                        archive(extra);
288
                        status = true;
289
                    }
290 7019 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
291
                    logMetacat.debug("Using resource: " + Constants.RESOURCE_CHECKSUM);
292 6756 cjones
293 6396 leinfelder
                    // after the command
294 7019 leinfelder
                    extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
295 6756 cjones
296
                    // handle checksum requests
297 6253 leinfelder
                    if (httpVerb == GET) {
298 6756 cjones
299 7019 leinfelder
                    	if (extra != null && extra.length() > 0) {
300
	                        checksum(extra);
301
	                        status = true;
302
                    	} else {
303
                    		listChecksumAlgorithms();
304
                    		status = true;
305
                    	}
306 6756 cjones
307 6253 leinfelder
                    }
308 6756 cjones
309
                } else if (resource.startsWith(RESOURCE_REPLICATION_POLICY)
310
                        && httpVerb == PUT) {
311
312
                    logMetacat.debug("Using resource: "
313
                            + RESOURCE_REPLICATION_POLICY);
314 6592 cjones
                    // get the trailing pid
315
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
316
                    setReplicationPolicy(extra);
317
                    status = true;
318
319 6756 cjones
                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
320
                        && httpVerb == PUT) {
321
322
                    logMetacat.debug("Using resource: "
323
                            + RESOURCE_REPLICATION_META);
324 6592 cjones
                    // get the trailing pid
325
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
326
                    updateReplicationMetadata(extra);
327
                    status = true;
328
329 6756 cjones
                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
330
                        && httpVerb == PUT) {
331
332
                    logMetacat.debug("Using resource: "
333
                            + RESOURCE_REPLICATION_NOTIFY);
334 6592 cjones
                    // get the trailing pid
335
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
336
                    setReplicationStatus(extra);
337
                    status = true;
338 6756 cjones
339
                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
340 6592 cjones
                        && httpVerb == GET) {
341 6756 cjones
342
                    logMetacat.debug("Using resource: "
343
                            + RESOURCE_REPLICATION_AUTHORIZED);
344 6592 cjones
                    // get the trailing pid
345 6756 cjones
                    extra = parseTrailing(resource,
346
                            RESOURCE_REPLICATION_AUTHORIZED);
347 6592 cjones
                    isNodeAuthorized(extra);
348
                    status = true;
349 6756 cjones
350 6803 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_MONITOR_PING)) {
351
                    if (httpVerb == GET) {
352
                    	// after the command
353
                        extra = parseTrailing(resource, Constants.RESOURCE_MONITOR_PING);
354
355
                        logMetacat.debug("processing ping request");
356
                        Date result = CNodeService.getInstance(request).ping();
357
                        // TODO: send to output
358
                        status = true;
359
                    }
360 6890 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_META_OBSOLETEDBY)
361
                        && httpVerb == PUT) {
362
363
                    logMetacat.debug("Using resource: "
364
                            + Constants.RESOURCE_META_OBSOLETEDBY);
365
                    // get the trailing pid
366
                    extra = parseTrailing(resource, Constants.RESOURCE_META_OBSOLETEDBY);
367
                    setObsoletedBy(extra);
368
                    status = true;
369 6891 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_REPLICATION_DELETE_REPLICA)
370
                        && httpVerb == PUT) {
371 6890 leinfelder
372 6891 leinfelder
                    logMetacat.debug("Using resource: "
373
                            + Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
374
                    // get the trailing pid
375
                    extra = parseTrailing(resource, Constants.RESOURCE_REPLICATION_DELETE_REPLICA);
376 7026 leinfelder
                    deleteReplica(extra);
377 6891 leinfelder
                    status = true;
378 6756 cjones
                }
379
380 6253 leinfelder
                if (!status) {
381 6756 cjones
                    throw new ServiceFailure("0000", "Unknown error, status = "
382
                            + status);
383 6253 leinfelder
                }
384
            } else {
385 6756 cjones
                throw new InvalidRequest("0000", "No resource matched for "
386
                        + resource);
387 6253 leinfelder
            }
388
        } catch (BaseException be) {
389 6756 cjones
            // report Exceptions as clearly and generically as possible
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 6253 leinfelder
            serializeException(be, out);
398
        } catch (Exception e) {
399 6270 leinfelder
            // report Exceptions as clearly and generically as possible
400 6253 leinfelder
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
401 6756 cjones
            OutputStream out = null;
402
            try {
403
                out = response.getOutputStream();
404
            } catch (IOException ioe) {
405
                logMetacat.error("Could not get output stream from response",
406
                        ioe);
407
            }
408
            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
409 6270 leinfelder
            serializeException(se, out);
410 6253 leinfelder
        }
411
    }
412 6756 cjones
413 6270 leinfelder
    /**
414
     * Get the checksum for the given guid
415
     *
416
     * @param guid
417 6756 cjones
     * @throws NotImplemented
418
     * @throws InvalidRequest
419
     * @throws NotFound
420
     * @throws NotAuthorized
421
     * @throws ServiceFailure
422
     * @throws InvalidToken
423
     * @throws IOException
424
     * @throws JiBXException
425 6270 leinfelder
     */
426 6756 cjones
    private void checksum(String guid) throws InvalidToken, ServiceFailure,
427
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
428
            JiBXException, IOException {
429
        Identifier guidid = new Identifier();
430 6270 leinfelder
        guidid.setValue(guid);
431
        logMetacat.debug("getting checksum for object " + guid);
432 6756 cjones
        Checksum c = CNodeService.getInstance(request).getChecksum(session,
433
                guidid);
434 6270 leinfelder
        logMetacat.debug("got checksum " + c.getValue());
435
        response.setStatus(200);
436
        logMetacat.debug("serializing response");
437 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
438 6270 leinfelder
        logMetacat.debug("done serializing response.");
439 6756 cjones
440 6270 leinfelder
    }
441 6756 cjones
442
    /**
443
     * get the logs based on passed params. Available params are token,
444
     * fromDate, toDate, event. See
445
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
446
     * .html#MN_crud.getLogRecords for more info
447
     *
448
     * @throws NotImplemented
449
     * @throws InvalidRequest
450
     * @throws NotAuthorized
451
     * @throws ServiceFailure
452
     * @throws InvalidToken
453
     * @throws IOException
454
     * @throws JiBXException
455 6253 leinfelder
     */
456 6756 cjones
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
457
            InvalidRequest, NotImplemented, IOException, JiBXException {
458
459 6270 leinfelder
        Date fromDate = null;
460
        Date toDate = null;
461
        Event event = null;
462
        Integer start = null;
463
        Integer count = null;
464 7099 leinfelder
        String pidFilter = null;
465 6756 cjones
466 6270 leinfelder
        try {
467 6756 cjones
            String fromDateS = params.get("fromDate")[0];
468 6272 leinfelder
            logMetacat.debug("param fromDateS: " + fromDateS);
469 6469 leinfelder
            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
470 6270 leinfelder
        } catch (Exception e) {
471 6756 cjones
            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
472 6253 leinfelder
        }
473 6270 leinfelder
        try {
474 6756 cjones
            String toDateS = params.get("toDate")[0];
475 6272 leinfelder
            logMetacat.debug("param toDateS: " + toDateS);
476 6469 leinfelder
            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
477 6270 leinfelder
        } catch (Exception e) {
478 6756 cjones
            logMetacat.warn("Could not parse toDate: " + e.getMessage());
479
        }
480 6270 leinfelder
        try {
481 6756 cjones
            String eventS = params.get("event")[0];
482 6270 leinfelder
            event = Event.convert(eventS);
483
        } catch (Exception e) {
484 6756 cjones
            logMetacat.warn("Could not parse event: " + e.getMessage());
485
        }
486 6272 leinfelder
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
487 6756 cjones
488 6270 leinfelder
        try {
489 6756 cjones
            start = Integer.parseInt(params.get("start")[0]);
490 6270 leinfelder
        } catch (Exception e) {
491 6756 cjones
            logMetacat.warn("Could not parse start: " + e.getMessage());
492
        }
493 6270 leinfelder
        try {
494 6756 cjones
            count = Integer.parseInt(params.get("count")[0]);
495 6270 leinfelder
        } catch (Exception e) {
496 6756 cjones
            logMetacat.warn("Could not parse count: " + e.getMessage());
497
        }
498
499 7099 leinfelder
        try {
500
            pidFilter = params.get("pidFilter")[0];
501
        } catch (Exception e) {
502
            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
503
        }
504
505 6272 leinfelder
        logMetacat.debug("calling getLogRecords");
506 6756 cjones
        Log log = CNodeService.getInstance(request).getLogRecords(session,
507 7101 leinfelder
                fromDate, toDate, event, pidFilter, start, count);
508 6756 cjones
509 6270 leinfelder
        OutputStream out = response.getOutputStream();
510
        response.setStatus(200);
511
        response.setContentType("text/xml");
512 6756 cjones
513 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(log, out);
514 6756 cjones
515 6253 leinfelder
    }
516
517
    /**
518
     * Implements REST version of DataONE CRUD API --> get
519 6756 cjones
     *
520
     * @param guid
521
     *            ID of data object to be read
522
     * @throws NotImplemented
523
     * @throws InvalidRequest
524
     * @throws NotFound
525
     * @throws NotAuthorized
526
     * @throws ServiceFailure
527
     * @throws InvalidToken
528
     * @throws IOException
529 6253 leinfelder
     */
530 6756 cjones
    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
531
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
532
            IOException {
533 6270 leinfelder
534 6280 leinfelder
        Identifier id = new Identifier();
535
        id.setValue(guid);
536 6756 cjones
537
        SystemMetadata sm = CNodeService.getInstance(request)
538
                .getSystemMetadata(session, id);
539
540 7316 leinfelder
        // set the content type, default to octet-stream
541
        response.setContentType("application/octet-stream");
542
        response.setHeader("Content-Disposition",
543
                "inline; filename=" + id.getValue());
544
        // TODO: use objectFormat MIME type when we add that information
545
        if (sm.getFormatId().getValue().startsWith("text")) {
546
            response.setContentType(sm.getFormatId().getValue());
547
        } else if (sm.getFormatId().getValue().startsWith("image")) {
548
        	response.setContentType(sm.getFormatId().getValue());
549
        } else if (sm.getFormatId().getValue().startsWith("application")) {
550
        	response.setContentType(sm.getFormatId().getValue());
551
        } else if (ObjectFormatCache.getInstance().getFormat(sm.getFormatId()).getFormatType().equals("METADATA")) {
552
        	response.setContentType("text/xml");
553 6280 leinfelder
        }
554 6756 cjones
555 6542 leinfelder
        InputStream data = CNodeService.getInstance(request).get(session, id);
556 6756 cjones
557 6280 leinfelder
        OutputStream out = response.getOutputStream();
558
        response.setStatus(200);
559
        IOUtils.copyLarge(data, out);
560 6756 cjones
561 6253 leinfelder
    }
562
563
    /**
564
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
565 6756 cjones
     *
566
     * @param guid
567
     *            ID of data object to be read
568
     * @throws NotImplemented
569
     * @throws InvalidRequest
570
     * @throws NotFound
571
     * @throws NotAuthorized
572
     * @throws ServiceFailure
573
     * @throws InvalidToken
574
     * @throws IOException
575
     * @throws JiBXException
576 6253 leinfelder
     */
577 6756 cjones
    protected void getSystemMetadataObject(String guid) throws InvalidToken,
578
            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
579
            NotImplemented, IOException, JiBXException {
580 6270 leinfelder
581
        Identifier id = new Identifier();
582
        id.setValue(guid);
583 6756 cjones
        SystemMetadata sysmeta = CNodeService.getInstance(request)
584
                .getSystemMetadata(session, id);
585
586 6270 leinfelder
        response.setContentType("text/xml");
587
        response.setStatus(200);
588
        OutputStream out = response.getOutputStream();
589 6756 cjones
590 6270 leinfelder
        // Serialize and write it to the output stream
591 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
592 6756 cjones
    }
593
594 6253 leinfelder
    /**
595 6756 cjones
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
596
     * handleInsertOrUpdateAction
597 6253 leinfelder
     *
598 6756 cjones
     * @param guid
599
     *            - ID of data object to be inserted or updated. If action is
600
     *            update, the pid is the existing pid. If insert, the pid is the
601
     *            new one
602
     * @throws InvalidRequest
603
     * @throws ServiceFailure
604
     * @throws IdentifierNotUnique
605
     * @throws JiBXException
606
     * @throws NotImplemented
607
     * @throws InvalidSystemMetadata
608
     * @throws InsufficientResources
609
     * @throws UnsupportedType
610
     * @throws NotAuthorized
611
     * @throws InvalidToken
612
     * @throws IOException
613
     * @throws IllegalAccessException
614
     * @throws InstantiationException
615 6253 leinfelder
     */
616 6973 leinfelder
    protected void putObject(String action) throws ServiceFailure,
617 6756 cjones
            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
618
            NotAuthorized, UnsupportedType, InsufficientResources,
619
            InvalidSystemMetadata, NotImplemented, IOException,
620
            InstantiationException, IllegalAccessException {
621 6973 leinfelder
622 6269 leinfelder
        // Read the incoming data from its Mime Multipart encoding
623 6756 cjones
        Map<String, File> files = collectMultipartFiles();
624 6973 leinfelder
625 6974 leinfelder
	    // get the encoded pid string from the body and make the object
626 6975 leinfelder
        String pidString = multipartparams.get("pid").get(0);
627
        Identifier pid = new Identifier();
628
        pid.setValue(pidString);
629 6973 leinfelder
630
        logMetacat.debug("putObject: " + pid.getValue() + "/" + action);
631
632 6269 leinfelder
        InputStream object = null;
633
        InputStream sysmeta = null;
634 6253 leinfelder
635 6269 leinfelder
        File smFile = files.get("sysmeta");
636
        sysmeta = new FileInputStream(smFile);
637
        File objFile = files.get("object");
638
        object = new FileInputStream(objFile);
639 6253 leinfelder
640 6756 cjones
        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
641
642 6269 leinfelder
            logMetacat.debug("Commence creation...");
643 6756 cjones
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
644
                    SystemMetadata.class, sysmeta);
645 6253 leinfelder
646 6973 leinfelder
647
            logMetacat.debug("creating object with pid " + pid.getValue());
648
            Identifier rId = CNodeService.getInstance(request).create(session, pid, object, smd);
649 6756 cjones
650 6269 leinfelder
            OutputStream out = response.getOutputStream();
651
            response.setStatus(200);
652
            response.setContentType("text/xml");
653 6756 cjones
654 6367 leinfelder
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
655 6756 cjones
656 6269 leinfelder
        } else {
657
            throw new InvalidRequest("1000", "Operation must be create.");
658 6253 leinfelder
        }
659
    }
660
661
    /**
662
     * List the object formats registered with the system
663 6756 cjones
     *
664
     * @throws NotImplemented
665
     * @throws InsufficientResources
666
     * @throws NotFound
667
     * @throws ServiceFailure
668
     * @throws InvalidRequest
669
     * @throws IOException
670
     * @throws JiBXException
671 6253 leinfelder
     */
672 6756 cjones
    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
673
            InsufficientResources, NotImplemented, IOException, JiBXException {
674
        logMetacat.debug("Entering listFormats()");
675 6270 leinfelder
676 6756 cjones
        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
677
                .listFormats();
678
        // get the response output stream
679
        OutputStream out = response.getOutputStream();
680
        response.setStatus(200);
681
        response.setContentType("text/xml");
682
683
        // style the object with a processing directive
684
        String stylesheet = null;
685
        try {
686
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
687
        } catch (PropertyNotFoundException e) {
688
            logMetacat.warn("Could not locate DataONE types XSLT: "
689
                    + e.getMessage());
690
        }
691
692
        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
693
                stylesheet);
694
695 6253 leinfelder
    }
696 6803 leinfelder
697
    private void listChecksumAlgorithms() throws IOException, ServiceFailure,
698
			NotImplemented, JiBXException {
699
		logMetacat.debug("Entering listFormats()");
700 6253 leinfelder
701 6803 leinfelder
		ChecksumAlgorithmList result = CNodeService.getInstance(request).listChecksumAlgorithms();
702
703
		// get the response output stream
704
		OutputStream out = response.getOutputStream();
705
		response.setStatus(200);
706
		response.setContentType("text/xml");
707
708 7034 leinfelder
		TypeMarshaller.marshalTypeToOutputStream(result, out);
709 6803 leinfelder
710
	}
711
712 6756 cjones
    /**
713 6803 leinfelder
     * http://mule1.dataone.org/ArchitectureDocs-current/apis/CN_APIs.html#CNRead.describe
714
     * @param pid
715
     * @throws InvalidToken
716
     * @throws ServiceFailure
717
     * @throws NotAuthorized
718
     * @throws NotFound
719
     * @throws NotImplemented
720
     * @throws InvalidRequest
721
     */
722
    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
723
    {
724
        response.setContentType("text/xml");
725
726
        Identifier id = new Identifier();
727
        id.setValue(pid);
728 7043 leinfelder
729
        DescribeResponse dr = null;
730
        try {
731
            dr = CNodeService.getInstance(request).describe(session, id);
732
        } catch (BaseException e) {
733
        	response.setStatus(e.getCode());
734
        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
735
            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
736
            response.addHeader("DataONE-Exception-Description", e.getDescription());
737
            response.addHeader("DataONE-Exception-PID", id.getValue());
738
            return;
739
		}
740
741
        response.setStatus(200);
742 6803 leinfelder
        //response.addHeader("pid", pid);
743
        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
744
        response.addHeader("Content-Length", dr.getContent_Length() + "");
745
        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
746
        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
747
        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
748
749
    }
750 7077 leinfelder
751
    /**
752
     * Handle delete
753
     * @param pid ID of data object to be deleted
754
     * @throws IOException
755
     * @throws InvalidRequest
756
     * @throws NotImplemented
757
     * @throws NotFound
758
     * @throws NotAuthorized
759
     * @throws ServiceFailure
760
     * @throws InvalidToken
761
     * @throws JiBXException
762
     */
763
    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException
764
    {
765 6803 leinfelder
766 7077 leinfelder
        OutputStream out = response.getOutputStream();
767
        response.setStatus(200);
768
        response.setContentType("text/xml");
769
770
        Identifier id = new Identifier();
771
        id.setValue(pid);
772
773 7090 cjones
        logMetacat.debug("Calling delete for identifier " + pid);
774 7077 leinfelder
        CNodeService.getInstance(request).delete(session, id);
775
        TypeMarshaller.marshalTypeToOutputStream(id, out);
776
777
    }
778 7155 leinfelder
779
    /**
780
     * Archives the given pid
781
     * @param pid
782
     * @throws InvalidToken
783
     * @throws ServiceFailure
784
     * @throws NotAuthorized
785
     * @throws NotFound
786
     * @throws NotImplemented
787
     * @throws IOException
788
     * @throws JiBXException
789
     */
790
    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
791 7077 leinfelder
792 7155 leinfelder
        OutputStream out = response.getOutputStream();
793
        response.setStatus(200);
794
        response.setContentType("text/xml");
795
796
        Identifier id = new Identifier();
797
        id.setValue(pid);
798
799
        logMetacat.debug("Calling archive");
800
        CNodeService.getInstance(request).archive(session, id);
801
802
        TypeMarshaller.marshalTypeToOutputStream(id, out);
803
804
    }
805
806 6803 leinfelder
    /**
807 6253 leinfelder
     * Return the requested object format
808
     *
809 6756 cjones
     * @param fmtidStr
810
     *            the requested format identifier as a string
811
     * @throws NotImplemented
812
     * @throws InsufficientResources
813
     * @throws NotFound
814
     * @throws ServiceFailure
815
     * @throws InvalidRequest
816
     * @throws IOException
817
     * @throws JiBXException
818 6253 leinfelder
     */
819 6756 cjones
    private void getFormat(String fmtidStr) throws InvalidRequest,
820
            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
821
            IOException, JiBXException {
822
        logMetacat.debug("Entering listFormats()");
823
824
        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
825
        fmtid.setValue(fmtidStr);
826
827
        // get the specified object format
828
        ObjectFormat objectFormat = CNodeService.getInstance(request)
829
                .getFormat(fmtid);
830
831
        OutputStream out = response.getOutputStream();
832
        response.setStatus(200);
833
        response.setContentType("text/xml");
834
835
        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
836
837 6253 leinfelder
    }
838 6756 cjones
839 6253 leinfelder
    /**
840
     * Reserve the given Identifier
841 6756 cjones
     *
842 6253 leinfelder
     * @throws InvalidToken
843
     * @throws ServiceFailure
844
     * @throws NotAuthorized
845
     * @throws IdentifierNotUnique
846
     * @throws NotImplemented
847
     * @throws InvalidRequest
848
     */
849 7095 cjones
    private void reserve()
850
        throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique,
851
        NotImplemented, InvalidRequest {
852 6756 cjones
        Identifier pid = null;
853
        String scope = null;
854
        String format = null;
855 7095 cjones
856
        // Parse the params out of the multipart form data
857
        logMetacat.debug("Parsing reserve parameters from the mime multipart entity");
858
        try {
859
            collectMultipartParams();
860
861
        } catch (FileUploadException e1) {
862
            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
863
            e1.getMessage();
864
            logMetacat.debug(msg);
865
            throw new ServiceFailure("4210", msg);
866
867
        } catch (IOException e1) {
868
            String msg = "IOException: Couldn't parse the mime multipart information: " +
869
            e1.getMessage();
870
            logMetacat.debug(msg);
871
            throw new ServiceFailure("4210", msg);
872
873
        } catch (Exception e1) {
874
            String msg = "Exception: Couldn't parse the mime multipart information: " +
875
            e1.getMessage();
876
            logMetacat.debug(msg);
877
            throw new ServiceFailure("4210", msg);
878
879
        }
880
881 6756 cjones
        // gather the params
882
        try {
883 7095 cjones
            String id = multipartparams.get("pid").get(0);
884 6756 cjones
            pid = new Identifier();
885
            pid.setValue(id);
886 7095 cjones
887
        } catch (NullPointerException e) {
888
            String msg = "The 'pid' must be provided as a parameter and was not.";
889
            logMetacat.error(msg);
890
            throw new InvalidRequest("4200", msg);
891
892 6756 cjones
        }
893 7095 cjones
894
        // call the implementation
895 6756 cjones
        try {
896 7095 cjones
            Identifier resultPid = CNodeService.getInstance(request).reserveIdentifier(session, pid);
897
            OutputStream out = response.getOutputStream();
898
            response.setStatus(200);
899
            response.setContentType("text/xml");
900
            // send back the reserved pid
901
            TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
902
903
        } catch (IOException e) {
904
            String msg = "Couldn't write the identifier to the response output stream: " +
905
                e.getMessage();
906
            logMetacat.debug(msg);
907
            throw new ServiceFailure("4210", msg);
908
909
        } catch (JiBXException e) {
910
            String msg = "Couldn't marshall the identifier to the response output stream: " +
911
            e.getMessage();
912
            logMetacat.debug(msg);
913
            throw new ServiceFailure("4210", msg);
914
915 6756 cjones
        }
916 6253 leinfelder
    }
917 6756 cjones
918 6270 leinfelder
    /**
919
     *
920
     * @param id
921
     * @throws InvalidRequest
922
     * @throws InvalidToken
923
     * @throws ServiceFailure
924
     * @throws NotAuthorized
925
     * @throws NotFound
926
     * @throws NotImplemented
927
     * @throws IOException
928 6756 cjones
     * @throws JiBXException
929 6270 leinfelder
     */
930 6756 cjones
    private void resolve(String id) throws InvalidRequest, InvalidToken,
931
            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
932
            IOException, JiBXException {
933
        Identifier pid = new Identifier();
934
        pid.setValue(id);
935
        ObjectLocationList locationList = CNodeService.getInstance(request)
936
                .resolve(session, pid);
937
        OutputStream out = response.getOutputStream();
938
        response.setStatus(200);
939
        response.setContentType("text/xml");
940
        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
941
942 6253 leinfelder
    }
943
944 6270 leinfelder
    /**
945
     * Set the owner of a resource
946 6756 cjones
     *
947 6270 leinfelder
     * @param id
948
     * @throws InvalidToken
949
     * @throws ServiceFailure
950
     * @throws NotFound
951
     * @throws NotAuthorized
952
     * @throws NotImplemented
953
     * @throws InvalidRequest
954 6756 cjones
     * @throws IllegalAccessException
955
     * @throws InstantiationException
956 6869 cjones
     * @throws VersionMismatch
957 6270 leinfelder
     */
958 7093 cjones
    private void owner(String id)
959 7094 cjones
        throws InvalidToken, ServiceFailure, NotFound, NotAuthorized,
960
        NotImplemented, InvalidRequest, InstantiationException,
961 7093 cjones
        IllegalAccessException, VersionMismatch {
962 6756 cjones
963 6592 cjones
        Identifier pid = new Identifier();
964 6756 cjones
        pid.setValue(id);
965 6592 cjones
966
        long serialVersion = 0L;
967
        String serialVersionStr = null;
968 7093 cjones
        String userIdStr = null;
969
        Subject userId = null;
970
971
        // Parse the params out of the multipart form data
972
        // Read the incoming data from its Mime Multipart encoding
973
        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
974
        try {
975
            collectMultipartParams();
976
977
        } catch (FileUploadException e1) {
978
            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
979
            e1.getMessage();
980
            logMetacat.debug(msg);
981
            throw new ServiceFailure("4490", msg);
982 6756 cjones
983 7093 cjones
        } catch (IOException e1) {
984
            String msg = "IOException: Couldn't parse the mime multipart information: " +
985
            e1.getMessage();
986
            logMetacat.debug(msg);
987
            throw new ServiceFailure("4490", msg);
988
989
        } catch (Exception e1) {
990
            String msg = "Exception: Couldn't parse the mime multipart information: " +
991
            e1.getMessage();
992
            logMetacat.debug(msg);
993
            throw new ServiceFailure("4490", msg);
994
995
        }
996
997 6592 cjones
        // get the serialVersion
998
        try {
999 7093 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1000 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1001 7093 cjones
1002
        } catch (NumberFormatException nfe) {
1003
            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
1004
            logMetacat.error(msg);
1005
            throw new InvalidRequest("4442", msg);
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("4442", msg);
1011
1012
        }
1013 6756 cjones
1014 7093 cjones
        // get the subject userId that will become the rights holder
1015
        try {
1016
            userIdStr = multipartparams.get("userId").get(0);
1017
            userId = new Subject();
1018
            userId.setValue(userIdStr);
1019
1020 6592 cjones
        } catch (NullPointerException e) {
1021
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1022
            logMetacat.error(msg);
1023
            throw new InvalidRequest("4442", msg);
1024 7093 cjones
1025
        }
1026 6756 cjones
1027 7093 cjones
        // set the rights holder
1028
        Identifier retPid = CNodeService.getInstance(request).setRightsHolder(session, pid, userId, serialVersion);
1029
1030
        try {
1031
            OutputStream out = response.getOutputStream();
1032
            response.setStatus(200);
1033
            response.setContentType("text/xml");
1034
            TypeMarshaller.marshalTypeToOutputStream(retPid, out);
1035
1036
        } catch (IOException e) {
1037
            String msg = "Couldn't write the identifier to the response output stream: " +
1038
                e.getMessage();
1039
            logMetacat.debug(msg);
1040
            throw new ServiceFailure("4490", msg);
1041 7094 cjones
1042
        } catch (JiBXException e) {
1043
            String msg = "Couldn't marshall the identifier to the response output stream: " +
1044
            e.getMessage();
1045
            logMetacat.debug(msg);
1046
            throw new ServiceFailure("4490", msg);
1047
1048 6756 cjones
        }
1049 6253 leinfelder
    }
1050 6756 cjones
1051 6270 leinfelder
    /**
1052
     * Processes the authorization check for given id
1053 6756 cjones
     *
1054 6270 leinfelder
     * @param id
1055
     * @return
1056
     * @throws ServiceFailure
1057
     * @throws InvalidToken
1058
     * @throws NotFound
1059
     * @throws NotAuthorized
1060
     * @throws NotImplemented
1061
     * @throws InvalidRequest
1062
     */
1063 6756 cjones
    private boolean isAuthorized(String id) throws ServiceFailure,
1064
            InvalidToken, NotFound, NotAuthorized, NotImplemented,
1065
            InvalidRequest {
1066
        Identifier pid = new Identifier();
1067
        pid.setValue(id);
1068
        String permission = params.get("action")[0];
1069
        boolean result = CNodeService.getInstance(request).isAuthorized(
1070
                session, pid, Permission.convert(permission));
1071
        response.setStatus(200);
1072
        response.setContentType("text/xml");
1073
        return result;
1074 6253 leinfelder
    }
1075 6756 cjones
1076 6253 leinfelder
    /**
1077
     * Register System Metadata without data or metadata object
1078 6756 cjones
     *
1079
     * @param pid
1080
     *            identifier for System Metadata entry
1081
     * @throws JiBXException
1082
     * @throws FileUploadException
1083
     * @throws IOException
1084
     * @throws InvalidRequest
1085
     * @throws ServiceFailure
1086
     * @throws InvalidSystemMetadata
1087
     * @throws NotAuthorized
1088
     * @throws NotImplemented
1089
     * @throws IllegalAccessException
1090
     * @throws InstantiationException
1091 6253 leinfelder
     */
1092 6974 leinfelder
    protected void registerSystemMetadata()
1093 6756 cjones
            throws ServiceFailure, InvalidRequest, IOException,
1094
            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
1095
            InvalidSystemMetadata, InstantiationException,
1096
            IllegalAccessException {
1097 6974 leinfelder
1098
    	// Read the incoming data from its Mime Multipart encoding
1099
        Map<String, File> files = collectMultipartFiles();
1100
1101
    	// get the encoded pid string from the body and make the object
1102 6975 leinfelder
        String pidString = multipartparams.get("pid").get(0);
1103
        Identifier pid = new Identifier();
1104
        pid.setValue(pidString);
1105 6974 leinfelder
1106
        logMetacat.debug("registerSystemMetadata: " + pid);
1107 6253 leinfelder
1108 6756 cjones
        // get the system metadata from the request
1109 6974 leinfelder
        File smFile = files.get("sysmeta");
1110
        FileInputStream sysmeta = new FileInputStream(smFile);
1111
        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
1112 6253 leinfelder
1113 6974 leinfelder
        logMetacat.debug("registering system metadata with pid " + pid.getValue());
1114
        Identifier retGuid = CNodeService.getInstance(request).registerSystemMetadata(session, pid, systemMetadata);
1115 6756 cjones
1116 6880 leinfelder
        OutputStream out = response.getOutputStream();
1117 6756 cjones
        response.setStatus(200);
1118
        response.setContentType("text/xml");
1119 6880 leinfelder
1120
        TypeMarshaller.marshalTypeToOutputStream(retGuid, out);
1121 6756 cjones
1122
    }
1123
1124 6268 leinfelder
    /**
1125
     * set the access perms on a document
1126 6756 cjones
     *
1127
     * @throws JiBXException
1128
     * @throws InvalidRequest
1129
     * @throws NotImplemented
1130
     * @throws NotAuthorized
1131
     * @throws NotFound
1132
     * @throws ServiceFailure
1133
     * @throws InvalidToken
1134
     * @throws IllegalAccessException
1135
     * @throws InstantiationException
1136
     * @throws IOException
1137
     * @throws SAXException
1138
     * @throws ParserConfigurationException
1139 6869 cjones
     * @throws VersionMismatch
1140 6268 leinfelder
     */
1141 6756 cjones
    protected void setAccess(String pid) throws JiBXException, InvalidToken,
1142
            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
1143
            InvalidRequest, IOException, InstantiationException,
1144 6869 cjones
            IllegalAccessException, ParserConfigurationException, SAXException, VersionMismatch {
1145 6270 leinfelder
1146 6592 cjones
        long serialVersion = 0L;
1147
        String serialVersionStr = null;
1148 7090 cjones
        AccessPolicy accessPolicy = collectAccessPolicy();
1149 6756 cjones
1150 6592 cjones
        // get the serialVersion
1151
        try {
1152 7090 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1153 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1154 6756 cjones
1155 7090 cjones
        } catch (NumberFormatException nfe) {
1156
            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
1157
            logMetacat.error(msg);
1158
            throw new InvalidRequest("4402", msg);
1159
1160 6592 cjones
        } catch (NullPointerException e) {
1161
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1162
            logMetacat.error(msg);
1163
            throw new InvalidRequest("4402", msg);
1164 6756 cjones
1165 6592 cjones
        }
1166 6756 cjones
1167 6270 leinfelder
        Identifier id = new Identifier();
1168 6514 leinfelder
        id.setValue(pid);
1169 6756 cjones
1170
        CNodeService.getInstance(request).setAccessPolicy(session, id,
1171
                accessPolicy, serialVersion);
1172 6270 leinfelder
1173 6268 leinfelder
    }
1174 6756 cjones
1175 6268 leinfelder
    /**
1176 6756 cjones
     * List the objects
1177
     *
1178
     * @throws NotImplemented
1179
     * @throws InvalidRequest
1180
     * @throws NotAuthorized
1181
     * @throws ServiceFailure
1182
     * @throws InvalidToken
1183
     * @throws NotFound
1184
     * @throws IOException
1185 6622 leinfelder
     * @throws JiBXException
1186 6268 leinfelder
     * @throws Exception
1187
     */
1188 6756 cjones
    private void listObjects() throws InvalidToken, ServiceFailure,
1189
            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
1190
            IOException, JiBXException {
1191 6622 leinfelder
1192 6756 cjones
        Date startTime = null;
1193
        Date endTime = null;
1194 7100 leinfelder
        ObjectFormatIdentifier formatId = null;
1195 6756 cjones
        boolean replicaStatus = false;
1196
        int start = 0;
1197
        int count = -1;
1198
        Enumeration<String> paramlist = request.getParameterNames();
1199
        while (paramlist.hasMoreElements()) {
1200
            // parse the params and make the call
1201
            String name = paramlist.nextElement();
1202 7048 leinfelder
            String[] values = request.getParameterValues(name);
1203
            String value = null;
1204
            if (values != null && values.length > 0) {
1205
            	value = values[0];
1206
            	value = EncodingUtilities.decodeString(value);
1207
            }
1208 6622 leinfelder
1209 7046 cjones
            if (name.equals("fromDate") && value != null) {
1210 6756 cjones
                try {
1211 7048 leinfelder
                    startTime = DateTimeMarshaller.deserializeDateToUTC(value);
1212 6756 cjones
                } catch (Exception e) {
1213
                    // if we can't parse it, just don't use the startTime param
1214 7048 leinfelder
                    logMetacat.warn("Could not parse fromDate: " + value);
1215 6756 cjones
                    startTime = null;
1216
                }
1217 7046 cjones
            } else if (name.equals("toDate") && value != null) {
1218 6756 cjones
                try {
1219 7048 leinfelder
                    endTime = DateTimeMarshaller.deserializeDateToUTC(value);
1220 6756 cjones
                } catch (Exception e) {
1221
                    // if we can't parse it, just don't use the endTime param
1222 7048 leinfelder
                    logMetacat.warn("Could not parse toDate: " + value);
1223 6756 cjones
                    endTime = null;
1224
                }
1225 7100 leinfelder
            } else if (name.equals("formatId") && value != null) {
1226
            	formatId = new ObjectFormatIdentifier();
1227
            	formatId.setValue(value);
1228 6756 cjones
            } else if (name.equals("replicaStatus") && value != null) {
1229 7048 leinfelder
                replicaStatus = Boolean.parseBoolean(value);
1230 6756 cjones
            } else if (name.equals("start") && value != null) {
1231 7048 leinfelder
                start = Integer.valueOf(value);
1232 6756 cjones
            } else if (name.equals("count") && value != null) {
1233 7048 leinfelder
                count = Integer.valueOf(value);
1234 6756 cjones
            }
1235
        }
1236
        // make the call
1237 7046 cjones
        logMetacat.debug("session: " + session + " fromDate: " + startTime
1238 7100 leinfelder
                + " toDate: " + endTime + " formatId: " + formatId
1239 6756 cjones
                + " replicaStatus: " + replicaStatus + " start: " + start
1240 7048 leinfelder
                + " count: " + count);
1241 6622 leinfelder
1242 6756 cjones
        // get the list
1243
        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
1244 7100 leinfelder
                startTime, endTime, formatId, replicaStatus, start, count);
1245 6756 cjones
1246
        // send it
1247
        OutputStream out = response.getOutputStream();
1248
        response.setStatus(200);
1249
        response.setContentType("text/xml");
1250
1251
        // style the object with a processing directive
1252
        String stylesheet = null;
1253
        try {
1254
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
1255
        } catch (PropertyNotFoundException e) {
1256
            logMetacat.warn("Could not locate DataONE types XSLT: "
1257
                    + e.getMessage());
1258
        }
1259
1260
        // Serialize and write it to the output stream
1261
        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
1262
    }
1263
1264 6592 cjones
    /**
1265
     * Pass the request to get node replication authorization to CNodeService
1266
     *
1267 6756 cjones
     * @param pid
1268
     *            the identifier of the object to get authorization to replicate
1269 6592 cjones
     *
1270
     * @throws NotImplemented
1271
     * @throws NotAuthorized
1272
     * @throws InvalidToken
1273
     * @throws ServiceFailure
1274
     * @throws NotFound
1275
     * @throws InvalidRequest
1276
     */
1277 6756 cjones
    public boolean isNodeAuthorized(String pid) throws NotImplemented,
1278
            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
1279
            InvalidRequest {
1280
1281 6592 cjones
        boolean result = false;
1282
        Subject targetNodeSubject = new Subject();
1283
        String nodeSubject = null;
1284
        String replPermission = null;
1285 6756 cjones
1286 6592 cjones
        // get the pid
1287
        Identifier identifier = new Identifier();
1288
        identifier.setValue(pid);
1289 6756 cjones
1290 6592 cjones
        // get the target node subject
1291
        try {
1292
            nodeSubject = params.get("targetNodeSubject")[0];
1293
            targetNodeSubject.setValue(nodeSubject);
1294 6756 cjones
1295 6592 cjones
        } catch (NullPointerException e) {
1296
            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
1297
            logMetacat.error(msg);
1298
            throw new InvalidRequest("4873", msg);
1299 6756 cjones
1300 6592 cjones
        }
1301 6756 cjones
1302 6777 leinfelder
        result = CNodeService.getInstance(request).isNodeAuthorized(session, targetNodeSubject, identifier);
1303 6268 leinfelder
1304 6592 cjones
        response.setStatus(200);
1305
        response.setContentType("text/xml");
1306
        return result;
1307 6756 cjones
1308 6592 cjones
    }
1309 6756 cjones
1310 6592 cjones
    /**
1311
     * Pass the request to set the replication policy to CNodeService
1312
     *
1313 6756 cjones
     * @param pid
1314
     *            the identifier of the object to set the replication policy on
1315 6592 cjones
     *
1316
     * @throws NotImplemented
1317
     * @throws NotFound
1318
     * @throws NotAuthorized
1319
     * @throws ServiceFailure
1320
     * @throws InvalidRequest
1321
     * @throws InvalidToken
1322
     * @throws IOException
1323
     * @throws InstantiationException
1324
     * @throws IllegalAccessException
1325
     * @throws JiBXException
1326 6869 cjones
     * @throws VersionMismatch
1327 6592 cjones
     */
1328 6756 cjones
    public boolean setReplicationPolicy(String pid) throws NotImplemented,
1329
            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
1330
            InvalidToken, IOException, InstantiationException,
1331 6869 cjones
            IllegalAccessException, JiBXException, VersionMismatch {
1332 6756 cjones
1333 6592 cjones
        boolean result = false;
1334
        ReplicationPolicy policy = null;
1335
        long serialVersion = 0L;
1336
        String serialVersionStr = null;
1337 6756 cjones
1338 6592 cjones
        Identifier identifier = new Identifier();
1339
        identifier.setValue(pid);
1340 6756 cjones
1341 6634 cjones
        policy = collectReplicationPolicy();
1342
1343 6592 cjones
        // get the serialVersion
1344
        try {
1345 6603 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1346 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1347 6756 cjones
1348 6592 cjones
        } catch (NullPointerException e) {
1349
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1350
            logMetacat.error(msg);
1351
            throw new InvalidRequest("4883", msg);
1352 6756 cjones
1353 6592 cjones
        }
1354 6756 cjones
        result = CNodeService.getInstance(request).setReplicationPolicy(
1355
                session, identifier, policy, serialVersion);
1356 6592 cjones
        response.setStatus(200);
1357
        response.setContentType("text/xml");
1358
        return result;
1359 6756 cjones
1360 6592 cjones
    }
1361 6890 leinfelder
1362 7096 cjones
    /**
1363
     * Update the system metadata for a given pid, setting it to be obsoleted
1364
     * by the obsoletedByPid
1365
     *
1366
     * @param pid
1367
     * @return
1368
     * @throws NotImplemented
1369
     * @throws NotFound
1370
     * @throws NotAuthorized
1371
     * @throws ServiceFailure
1372
     * @throws InvalidRequest
1373
     * @throws InvalidToken
1374
     * @throws InstantiationException
1375
     * @throws IllegalAccessException
1376
     * @throws VersionMismatch
1377
     */
1378
    public boolean setObsoletedBy(String pid)
1379
        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
1380
        InvalidRequest, InvalidToken, InstantiationException,
1381
        IllegalAccessException, VersionMismatch {
1382
1383
        boolean result = false;
1384
        long serialVersion = 0L;
1385
        String serialVersionStr = null;
1386
1387
        Identifier identifier = new Identifier();
1388
        identifier.setValue(pid);
1389
        String obsoletedByPidString = null;
1390
        Identifier obsoletedByPid = null;
1391
1392
        // Parse the params out of the multipart form data
1393
        // Read the incoming data from its Mime Multipart encoding
1394
        logMetacat.debug("Parsing rights holder parameters from the mime multipart entity");
1395
        try {
1396
            collectMultipartParams();
1397
1398
        } catch (FileUploadException e1) {
1399
            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
1400
            e1.getMessage();
1401
            logMetacat.debug(msg);
1402
            throw new ServiceFailure("4941", msg);
1403
1404
        } catch (IOException e1) {
1405
            String msg = "IOException: Couldn't parse the mime multipart information: " +
1406
            e1.getMessage();
1407
            logMetacat.debug(msg);
1408
            throw new ServiceFailure("4941", msg);
1409
1410
        } catch (Exception e1) {
1411
            String msg = "Exception: Couldn't parse the mime multipart information: " +
1412
            e1.getMessage();
1413
            logMetacat.debug(msg);
1414
            throw new ServiceFailure("4941", msg);
1415
1416
        }
1417
1418
        // get the obsoletedByPid
1419
        try {
1420
            obsoletedByPidString = multipartparams.get("obsoletedByPid").get(0);
1421
            obsoletedByPid = new Identifier();
1422
            obsoletedByPid.setValue(obsoletedByPidString);
1423
        } catch (NullPointerException e) {
1424
            String msg = "The 'obsoletedByPid' must be provided as a parameter and was not.";
1425
            logMetacat.error(msg);
1426
            throw new InvalidRequest("4883", msg);
1427
        }
1428
1429
        // get the serialVersion
1430
        try {
1431
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1432
            serialVersion = new Long(serialVersionStr).longValue();
1433
1434
        } catch (NumberFormatException nfe) {
1435
            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
1436
            logMetacat.error(msg);
1437
            throw new InvalidRequest("4942", msg);
1438
1439
        } catch (NullPointerException e) {
1440
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1441
            logMetacat.error(msg);
1442
            throw new InvalidRequest("4942", msg);
1443
1444
        }
1445
        result = CNodeService.getInstance(request).setObsoletedBy(session,
1446
            identifier, obsoletedByPid, serialVersion);
1447
        response.setStatus(200);
1448
        response.setContentType("text/xml");
1449
        return result;
1450
1451
    }
1452 6891 leinfelder
1453 7097 cjones
    /**
1454
     * Delete the replica entry with the given nodeId for the given pid
1455
     *
1456
     * @param pid
1457
     * @return
1458
     * @throws NotImplemented
1459
     * @throws NotFound
1460
     * @throws NotAuthorized
1461
     * @throws ServiceFailure
1462
     * @throws InvalidRequest
1463
     * @throws InvalidToken
1464
     * @throws InstantiationException
1465
     * @throws IllegalAccessException
1466
     * @throws VersionMismatch
1467
     */
1468
    public boolean deleteReplica(String pid)
1469
        throws NotImplemented, NotFound, NotAuthorized, ServiceFailure,
1470
        InvalidRequest, InvalidToken, InstantiationException,
1471
        IllegalAccessException, VersionMismatch {
1472 6891 leinfelder
1473 7097 cjones
        boolean result = false;
1474
        long serialVersion = 0L;
1475
        String serialVersionStr = null;
1476 6891 leinfelder
1477 7097 cjones
        Identifier identifier = new Identifier();
1478
        identifier.setValue(pid);
1479 6891 leinfelder
1480 7097 cjones
        NodeReference nodeId = null;
1481
1482
        // Parse the params out of the multipart form data
1483
        // Read the incoming data from its Mime Multipart encoding
1484
        logMetacat.debug("Parsing delete replica parameters from the mime multipart entity");
1485
        try {
1486
            collectMultipartParams();
1487
1488
        } catch (FileUploadException e1) {
1489
            String msg = "FileUploadException: Couldn't parse the mime multipart information: " +
1490
            e1.getMessage();
1491
            logMetacat.debug(msg);
1492
            throw new ServiceFailure("4951", msg);
1493 6891 leinfelder
1494 7097 cjones
        } catch (IOException e1) {
1495
            String msg = "IOException: Couldn't parse the mime multipart information: " +
1496
            e1.getMessage();
1497
            logMetacat.debug(msg);
1498
            throw new ServiceFailure("4951", msg);
1499
1500
        } catch (Exception e1) {
1501
            String msg = "Exception: Couldn't parse the mime multipart information: " +
1502
            e1.getMessage();
1503
            logMetacat.debug(msg);
1504
            throw new ServiceFailure("4951", msg);
1505 6891 leinfelder
1506 7097 cjones
        }
1507
1508
        // get the nodeId param
1509
        try {
1510
            String nodeIdString = multipartparams.get("nodeId").get(0);
1511
            nodeId = new NodeReference();
1512
            nodeId.setValue(nodeIdString);
1513
1514
        } catch (NullPointerException e) {
1515
            String msg = "The 'nodeId' must be provided as a parameter and was not.";
1516
            logMetacat.error(msg);
1517
            throw new InvalidRequest("4952", msg);
1518
        }
1519 6891 leinfelder
1520 7097 cjones
        // get the serialVersion
1521
        try {
1522
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1523
            serialVersion = new Long(serialVersionStr).longValue();
1524
1525
        } catch (NumberFormatException nfe) {
1526
            String msg = "The 'serialVersion' must be provided as a positive integer and was not.";
1527
            logMetacat.error(msg);
1528
            throw new InvalidRequest("4952", msg);
1529
1530
        } catch (NullPointerException e) {
1531
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1532
            logMetacat.error(msg);
1533
            throw new InvalidRequest("4952", msg);
1534
1535
        }
1536
        result = CNodeService.getInstance(request).deleteReplicationMetadata(
1537
                session, identifier, nodeId, serialVersion);
1538
        response.setStatus(200);
1539
        response.setContentType("text/xml");
1540
        return result;
1541 6891 leinfelder
1542 7097 cjones
    }
1543 6756 cjones
1544 6592 cjones
    /**
1545
     * Pass the request to set the replication status to CNodeService
1546
     *
1547 6756 cjones
     * @param pid
1548
     *            the identifier of the object to set the replication status on
1549 6592 cjones
     *
1550
     * @throws ServiceFailure
1551
     * @throws NotImplemented
1552
     * @throws InvalidToken
1553
     * @throws NotAuthorized
1554
     * @throws InvalidRequest
1555
     * @throws NotFound
1556 6794 cjones
     * @throws JiBXException
1557
     * @throws IllegalAccessException
1558
     * @throws InstantiationException
1559
     * @throws IOException
1560 6592 cjones
     */
1561 6756 cjones
    public boolean setReplicationStatus(String pid) throws ServiceFailure,
1562
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1563
            NotFound {
1564 6794 cjones
1565 6592 cjones
        boolean result = false;
1566
        Identifier identifier = new Identifier();
1567
        identifier.setValue(pid);
1568 6794 cjones
        BaseException failure = null;
1569 6592 cjones
        ReplicationStatus status = null;
1570
        String replicationStatus = null;
1571
        NodeReference targetNodeRef = null;
1572
        String targetNode = null;
1573 6756 cjones
1574 6634 cjones
        // Parse the params out of the multipart form data
1575
        // Read the incoming data from its Mime Multipart encoding
1576 6794 cjones
        logMetacat.debug("Parsing ReplicaStatus from the mime multipart entity");
1577 6634 cjones
1578
        try {
1579 6794 cjones
            failure = collectReplicationStatus();
1580
1581
        } catch (IOException e2) {
1582
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1583
                e2.getMessage());
1584
1585
        } catch (InstantiationException e2) {
1586
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1587
                e2.getMessage());
1588
1589
        } catch (IllegalAccessException e2) {
1590
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1591
                    e2.getMessage());
1592
1593
        } catch (JiBXException e2) {
1594
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
1595
                    e2.getMessage());
1596
1597 6634 cjones
        }
1598 6794 cjones
1599 6592 cjones
        // get the replication status param
1600
        try {
1601 6643 cjones
            replicationStatus = multipartparams.get("status").get(0);
1602 6592 cjones
            status = ReplicationStatus.convert(replicationStatus);
1603 6677 cjones
1604 6642 cjones
        } catch (NullPointerException npe) {
1605
1606 6756 cjones
            logMetacat.debug("The 'status' parameter was not found in the "
1607
                    + "multipartparams map.  Trying the params map.");
1608
1609 6642 cjones
            try {
1610 6643 cjones
                replicationStatus = params.get("status")[0];
1611 6756 cjones
                status = ReplicationStatus.convert(replicationStatus
1612
                        .toLowerCase());
1613
1614 6642 cjones
            } catch (Exception e) {
1615 6643 cjones
                String msg = "The 'status' must be provided as a parameter and was not.";
1616 6642 cjones
                logMetacat.error(msg);
1617
                throw new InvalidRequest("4730", msg);
1618 6756 cjones
1619 6642 cjones
            }
1620 6756 cjones
1621 6592 cjones
        }
1622 6756 cjones
1623 6592 cjones
        // get the target node reference param
1624 6642 cjones
        try {
1625
            targetNode = multipartparams.get("nodeRef").get(0);
1626
            targetNodeRef = new NodeReference();
1627
            targetNodeRef.setValue(targetNode);
1628 6756 cjones
1629 6642 cjones
        } catch (NullPointerException e) {
1630 6756 cjones
            logMetacat.debug("The 'nodeRef' parameter was not found in the "
1631
                    + "multipartparams map.  Trying the params map.");
1632
1633 6642 cjones
            try {
1634
                targetNode = params.get("nodeRef")[0];
1635
                targetNodeRef = new NodeReference();
1636
                targetNodeRef.setValue(targetNode);
1637 6756 cjones
1638 6642 cjones
            } catch (Exception e1) {
1639
                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
1640
                logMetacat.error(msg);
1641
                throw new InvalidRequest("4730", msg);
1642 6756 cjones
1643 6642 cjones
            }
1644 6756 cjones
1645 6642 cjones
        }
1646 6756 cjones
1647
        result = CNodeService.getInstance(request).setReplicationStatus(
1648 6794 cjones
                session, identifier, targetNodeRef, status, failure);
1649 6592 cjones
        response.setStatus(200);
1650
        response.setContentType("text/xml");
1651
        return result;
1652 6756 cjones
1653 6592 cjones
    }
1654 6756 cjones
1655 6592 cjones
    /**
1656
     * Pass the request to update the replication metadata to CNodeService
1657
     *
1658 6756 cjones
     * @param pid
1659
     *            the identifier of the object to update the replication
1660
     *            metadata on
1661 6592 cjones
     *
1662
     * @throws ServiceFailure
1663
     * @throws NotImplemented
1664
     * @throws InvalidToken
1665
     * @throws NotAuthorized
1666
     * @throws InvalidRequest
1667
     * @throws NotFound
1668 6869 cjones
     * @throws VersionMismatch
1669 6592 cjones
     */
1670 6756 cjones
    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
1671
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1672 6869 cjones
            NotFound, VersionMismatch {
1673 6592 cjones
1674
        boolean result = false;
1675
        long serialVersion = 0L;
1676
        String serialVersionStr = null;
1677
        Replica replica = null;
1678
        Identifier identifier = new Identifier();
1679
        identifier.setValue(pid);
1680
1681 6634 cjones
        replica = collectReplicaMetadata();
1682 6756 cjones
1683 6592 cjones
        // get the serialVersion
1684
        try {
1685 6603 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1686 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1687 6756 cjones
1688 6592 cjones
        } catch (NullPointerException e) {
1689
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1690
            logMetacat.error(msg);
1691
            throw new InvalidRequest("4853", msg);
1692 6756 cjones
1693 6592 cjones
        }
1694
1695 6756 cjones
        result = CNodeService.getInstance(request).updateReplicationMetadata(
1696
                session, identifier, replica, serialVersion);
1697 6592 cjones
        response.setStatus(200);
1698
        response.setContentType("text/xml");
1699
        return result;
1700
1701
    }
1702
1703 6253 leinfelder
}