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