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.ByteArrayInputStream;
26
import java.io.File;
27
import java.io.FileInputStream;
28
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.util.Date;
32 6622 leinfelder
import java.util.Enumeration;
33 6253 leinfelder
import java.util.Map;
34
35
import javax.servlet.ServletContext;
36
import javax.servlet.http.HttpServletRequest;
37
import javax.servlet.http.HttpServletResponse;
38 6514 leinfelder
import javax.xml.parsers.ParserConfigurationException;
39 6253 leinfelder
40 6269 leinfelder
import org.apache.commons.fileupload.FileUploadException;
41 6253 leinfelder
import org.apache.commons.io.IOUtils;
42
import org.apache.log4j.Logger;
43
import org.dataone.client.ObjectFormatCache;
44 6634 cjones
import org.dataone.mimemultipart.MultipartRequest;
45
import org.dataone.mimemultipart.MultipartRequestResolver;
46 6253 leinfelder
import org.dataone.service.exceptions.BaseException;
47
import org.dataone.service.exceptions.IdentifierNotUnique;
48
import org.dataone.service.exceptions.InsufficientResources;
49
import org.dataone.service.exceptions.InvalidRequest;
50
import org.dataone.service.exceptions.InvalidSystemMetadata;
51
import org.dataone.service.exceptions.InvalidToken;
52
import org.dataone.service.exceptions.NotAuthorized;
53
import org.dataone.service.exceptions.NotFound;
54
import org.dataone.service.exceptions.NotImplemented;
55
import org.dataone.service.exceptions.ServiceFailure;
56
import org.dataone.service.exceptions.UnsupportedType;
57 6366 leinfelder
import org.dataone.service.types.v1.AccessPolicy;
58
import org.dataone.service.types.v1.Checksum;
59
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 6469 leinfelder
import org.dataone.service.util.DateTimeMarshaller;
75 6367 leinfelder
import org.dataone.service.util.TypeMarshaller;
76 6253 leinfelder
import org.jibx.runtime.JiBXException;
77 6514 leinfelder
import org.xml.sax.SAXException;
78 6253 leinfelder
79
import edu.ucsb.nceas.metacat.dataone.CNodeService;
80 6639 leinfelder
import edu.ucsb.nceas.metacat.properties.PropertyService;
81
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
82 6253 leinfelder
83
/**
84
 * CN REST service implementation handler
85
 *
86 6756 cjones
 * ****************** CNCore -- DONE create() - POST /d1/cn/object/PID
87
 * listFormats() - GET /d1/cn/formats getFormat() - GET /d1/cn/formats/FMTID
88
 * getLogRecords - GET /d1/cn/log reserveIdentifier() - POST /d1/cn/reserve
89
 * listNodes() - Not implemented registerSystemMetadata() - POST /d1/meta/PID
90
 *
91
 * CNRead -- DONE get() - GET /d1/cn/object/PID getSystemMetadata() - GET
92
 * /d1/cn/meta/PID resolve() - GET /d1/cn/resolve/PID assertRelation() - GET
93
 * /d1/cn/assertRelation/PID getChecksum() - GET /d1/cn/checksum search() - Not
94
 * implemented in Metacat
95
 *
96
 * CNAuthorization setOwner() - PUT /d1/cn/owner/PID isAuthorized() - GET
97
 * /d1/cn/isAuthorized/PID setAccessPolicy() - POST /d1/cn/accessRules
98
 *
99
 * CNIdentity - not implemented at all on Metacat
100
 *
101
 * CNReplication setReplicationStatus() - PUT /replicaNotifications/PID
102
 * updateReplicationMetadata() - PUT /replicaMetadata/PID setReplicationPolicy()
103
 * - PUT /replicaPolicies/PID isNodeAuthorized() - GET
104
 * /replicaAuthorizations/PID
105
 *
106
 * CNRegister -- not implemented at all in Metacat ******************
107
 *
108 6253 leinfelder
 * @author leinfelder
109 6756 cjones
 *
110 6253 leinfelder
 */
111 6267 leinfelder
public class CNResourceHandler extends D1ResourceHandler {
112 6253 leinfelder
113 6756 cjones
    /** CN-specific operations **/
114 6253 leinfelder
    protected static final String RESOURCE_RESERVE = "reserve";
115 6271 leinfelder
    protected static final String RESOURCE_FORMATS = "formats";
116 6253 leinfelder
    protected static final String RESOURCE_RESOLVE = "resolve";
117
    protected static final String RESOURCE_ASSERT_RELATION = "assertRelation";
118
    protected static final String RESOURCE_OWNER = "owner";
119 6592 cjones
    protected static final String RESOURCE_REPLICATION_POLICY = "replicaPolicies";
120
    protected static final String RESOURCE_REPLICATION_META = "replicaMetadata";
121
    protected static final String RESOURCE_REPLICATION_AUTHORIZED = "replicaAuthorizations";
122
    protected static final String RESOURCE_REPLICATION_NOTIFY = "replicaNotifications";
123 6756 cjones
124 6253 leinfelder
    public CNResourceHandler(ServletContext servletContext,
125 6756 cjones
            HttpServletRequest request, HttpServletResponse response) {
126
        super(servletContext, request, response);
127 6253 leinfelder
        logMetacat = Logger.getLogger(CNResourceHandler.class);
128 6756 cjones
    }
129 6253 leinfelder
130 6756 cjones
    /**
131
     * This function is called from REST API servlet and handles each request to
132
     * the servlet
133 6253 leinfelder
     *
134 6756 cjones
     * @param httpVerb
135
     *            (GET, POST, PUT or DELETE)
136 6253 leinfelder
     */
137 6271 leinfelder
    @Override
138 6253 leinfelder
    public void handle(byte httpVerb) {
139 6756 cjones
        // prepare the handler
140
        super.handle(httpVerb);
141
142 6253 leinfelder
        try {
143 6282 leinfelder
144 6756 cjones
            // get the resource
145 6282 leinfelder
            String resource = request.getPathInfo();
146
            resource = resource.substring(resource.indexOf("/") + 1);
147 6756 cjones
148 6396 leinfelder
            // for the rest of the resouce
149 6282 leinfelder
            String extra = null;
150 6756 cjones
151
            logMetacat.debug("handling verb " + httpVerb
152
                    + " request with resource '" + resource + "'");
153 6253 leinfelder
            boolean status = false;
154 6271 leinfelder
155 6253 leinfelder
            if (resource != null) {
156
157 6756 cjones
                if (resource.startsWith(RESOURCE_ACCESS_RULES)
158
                        && httpVerb == PUT) {
159 6253 leinfelder
                    logMetacat.debug("Setting access policy");
160 6514 leinfelder
                    // after the command
161
                    extra = parseTrailing(resource, RESOURCE_ACCESS_RULES);
162
                    setAccess(extra);
163 6253 leinfelder
                    status = true;
164
                    logMetacat.debug("done setting access");
165 6756 cjones
166 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_META)) {
167 6253 leinfelder
                    logMetacat.debug("Using resource: " + RESOURCE_META);
168 6756 cjones
169 6396 leinfelder
                    // after the command
170
                    extra = parseTrailing(resource, RESOURCE_META);
171 6756 cjones
172 6253 leinfelder
                    // get
173
                    if (httpVerb == GET) {
174 6282 leinfelder
                        getSystemMetadataObject(extra);
175 6253 leinfelder
                        status = true;
176
                    }
177
                    // post to register system metadata
178
                    if (httpVerb == POST) {
179 6756 cjones
                        registerSystemMetadata(extra);
180
                        status = true;
181 6253 leinfelder
                    }
182
183 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_RESERVE)) {
184 6253 leinfelder
                    // reserve the ID (in params)
185
                    if (httpVerb == POST) {
186 6756 cjones
                        reserve();
187
                        status = true;
188 6253 leinfelder
                    }
189 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_ASSERT_RELATION)) {
190 6756 cjones
191
                    // after the command
192 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_ASSERT_RELATION);
193 6756 cjones
194 6253 leinfelder
                    // reserve the ID (in params)
195
                    if (httpVerb == GET) {
196 6756 cjones
                        assertRelation(extra);
197
                        status = true;
198
                    }
199 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_RESOLVE)) {
200 6756 cjones
201
                    // after the command
202 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_RESOLVE);
203 6756 cjones
204 6253 leinfelder
                    // resolve the object location
205
                    if (httpVerb == GET) {
206 6756 cjones
                        resolve(extra);
207
                        status = true;
208 6253 leinfelder
                    }
209 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_OWNER)) {
210 6756 cjones
211
                    // after the command
212 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_OWNER);
213 6756 cjones
214 6253 leinfelder
                    // set the owner
215
                    if (httpVerb == PUT) {
216 6756 cjones
                        owner(extra);
217
                        status = true;
218
                    }
219 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
220 6756 cjones
221
                    // after the command
222 6396 leinfelder
                    extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
223 6756 cjones
224 6253 leinfelder
                    // authorized?
225
                    if (httpVerb == GET) {
226 6756 cjones
                        isAuthorized(extra);
227
                        status = true;
228
                    }
229 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
230 6253 leinfelder
                    logMetacat.debug("Using resource 'object'");
231 6756 cjones
                    logMetacat
232
                            .debug("D1 Rest: Starting resource processing...");
233
234 6396 leinfelder
                    // after the command
235
                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
236 6756 cjones
237 6282 leinfelder
                    logMetacat.debug("objectId: " + extra);
238 6253 leinfelder
                    logMetacat.debug("verb:" + httpVerb);
239
240
                    if (httpVerb == GET) {
241 6756 cjones
                        if (extra != null) {
242
                            getObject(extra);
243
                        } else {
244
                            listObjects();
245
                        }
246 6253 leinfelder
                        status = true;
247
                    } else if (httpVerb == POST) {
248 6282 leinfelder
                        putObject(extra, FUNCTION_NAME_INSERT);
249 6253 leinfelder
                        status = true;
250
                    }
251 6756 cjones
252 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_FORMATS)) {
253 6756 cjones
                    logMetacat.debug("Using resource: " + RESOURCE_FORMATS);
254
255
                    // after the command
256
                    extra = parseTrailing(resource, RESOURCE_FORMATS);
257
258
                    // handle each verb
259
                    if (httpVerb == GET) {
260
                        if (extra == null) {
261
                            // list the formats collection
262
                            listFormats();
263
                        } else {
264
                            // get the specified format
265
                            getFormat(extra);
266
                        }
267
                        status = true;
268
                    }
269
270 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_LOG)) {
271 6253 leinfelder
                    logMetacat.debug("Using resource: " + RESOURCE_LOG);
272 6756 cjones
                    // handle log events
273 6253 leinfelder
                    if (httpVerb == GET) {
274
                        getLog();
275
                        status = true;
276
                    }
277
278 6282 leinfelder
                } else if (resource.startsWith(RESOURCE_CHECKSUM)) {
279 6253 leinfelder
                    logMetacat.debug("Using resource: " + RESOURCE_CHECKSUM);
280 6756 cjones
281 6396 leinfelder
                    // after the command
282
                    extra = parseTrailing(resource, RESOURCE_CHECKSUM);
283 6756 cjones
284
                    // handle checksum requests
285 6253 leinfelder
                    if (httpVerb == GET) {
286 6756 cjones
287 6282 leinfelder
                        checksum(extra);
288 6253 leinfelder
                        status = true;
289 6756 cjones
290 6253 leinfelder
                    }
291 6756 cjones
292
                } else if (resource.startsWith(RESOURCE_REPLICATION_POLICY)
293
                        && httpVerb == PUT) {
294
295
                    logMetacat.debug("Using resource: "
296
                            + RESOURCE_REPLICATION_POLICY);
297 6592 cjones
                    // get the trailing pid
298
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_POLICY);
299
                    setReplicationPolicy(extra);
300
                    status = true;
301
302 6756 cjones
                } else if (resource.startsWith(RESOURCE_REPLICATION_META)
303
                        && httpVerb == PUT) {
304
305
                    logMetacat.debug("Using resource: "
306
                            + RESOURCE_REPLICATION_META);
307 6592 cjones
                    // get the trailing pid
308
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_META);
309
                    updateReplicationMetadata(extra);
310
                    status = true;
311
312 6756 cjones
                } else if (resource.startsWith(RESOURCE_REPLICATION_NOTIFY)
313
                        && httpVerb == PUT) {
314
315
                    logMetacat.debug("Using resource: "
316
                            + RESOURCE_REPLICATION_NOTIFY);
317 6592 cjones
                    // get the trailing pid
318
                    extra = parseTrailing(resource, RESOURCE_REPLICATION_NOTIFY);
319
                    setReplicationStatus(extra);
320
                    status = true;
321 6756 cjones
322
                } else if (resource.startsWith(RESOURCE_REPLICATION_AUTHORIZED)
323 6592 cjones
                        && httpVerb == GET) {
324 6756 cjones
325
                    logMetacat.debug("Using resource: "
326
                            + RESOURCE_REPLICATION_AUTHORIZED);
327 6592 cjones
                    // get the trailing pid
328 6756 cjones
                    extra = parseTrailing(resource,
329
                            RESOURCE_REPLICATION_AUTHORIZED);
330 6592 cjones
                    isNodeAuthorized(extra);
331
                    status = true;
332 6756 cjones
333
                }
334
335 6253 leinfelder
                if (!status) {
336 6756 cjones
                    throw new ServiceFailure("0000", "Unknown error, status = "
337
                            + status);
338 6253 leinfelder
                }
339
            } else {
340 6756 cjones
                throw new InvalidRequest("0000", "No resource matched for "
341
                        + resource);
342 6253 leinfelder
            }
343
        } catch (BaseException be) {
344 6756 cjones
            // report Exceptions as clearly and generically as possible
345
            OutputStream out = null;
346
            try {
347
                out = response.getOutputStream();
348
            } catch (IOException ioe) {
349
                logMetacat.error("Could not get output stream from response",
350
                        ioe);
351
            }
352 6253 leinfelder
            serializeException(be, out);
353
        } catch (Exception e) {
354 6270 leinfelder
            // report Exceptions as clearly and generically as possible
355 6253 leinfelder
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
356 6756 cjones
            OutputStream out = null;
357
            try {
358
                out = response.getOutputStream();
359
            } catch (IOException ioe) {
360
                logMetacat.error("Could not get output stream from response",
361
                        ioe);
362
            }
363
            ServiceFailure se = new ServiceFailure("0000", e.getMessage());
364 6270 leinfelder
            serializeException(se, out);
365 6253 leinfelder
        }
366
    }
367 6756 cjones
368 6270 leinfelder
    /**
369
     * Get the checksum for the given guid
370
     *
371
     * @param guid
372 6756 cjones
     * @throws NotImplemented
373
     * @throws InvalidRequest
374
     * @throws NotFound
375
     * @throws NotAuthorized
376
     * @throws ServiceFailure
377
     * @throws InvalidToken
378
     * @throws IOException
379
     * @throws JiBXException
380 6270 leinfelder
     */
381 6756 cjones
    private void checksum(String guid) throws InvalidToken, ServiceFailure,
382
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
383
            JiBXException, IOException {
384
        Identifier guidid = new Identifier();
385 6270 leinfelder
        guidid.setValue(guid);
386
        logMetacat.debug("getting checksum for object " + guid);
387 6756 cjones
        Checksum c = CNodeService.getInstance(request).getChecksum(session,
388
                guidid);
389 6270 leinfelder
        logMetacat.debug("got checksum " + c.getValue());
390
        response.setStatus(200);
391
        logMetacat.debug("serializing response");
392 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
393 6270 leinfelder
        logMetacat.debug("done serializing response.");
394 6756 cjones
395 6270 leinfelder
    }
396 6756 cjones
397
    /**
398
     * get the logs based on passed params. Available params are token,
399
     * fromDate, toDate, event. See
400
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud
401
     * .html#MN_crud.getLogRecords for more info
402
     *
403
     * @throws NotImplemented
404
     * @throws InvalidRequest
405
     * @throws NotAuthorized
406
     * @throws ServiceFailure
407
     * @throws InvalidToken
408
     * @throws IOException
409
     * @throws JiBXException
410 6253 leinfelder
     */
411 6756 cjones
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized,
412
            InvalidRequest, NotImplemented, IOException, JiBXException {
413
414 6270 leinfelder
        Date fromDate = null;
415
        Date toDate = null;
416
        Event event = null;
417
        Integer start = null;
418
        Integer count = null;
419 6756 cjones
420 6270 leinfelder
        try {
421 6756 cjones
            String fromDateS = params.get("fromDate")[0];
422 6272 leinfelder
            logMetacat.debug("param fromDateS: " + fromDateS);
423 6469 leinfelder
            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
424 6270 leinfelder
        } catch (Exception e) {
425 6756 cjones
            logMetacat.warn("Could not parse fromDate: " + e.getMessage());
426 6253 leinfelder
        }
427 6270 leinfelder
        try {
428 6756 cjones
            String toDateS = params.get("toDate")[0];
429 6272 leinfelder
            logMetacat.debug("param toDateS: " + toDateS);
430 6469 leinfelder
            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
431 6270 leinfelder
        } catch (Exception e) {
432 6756 cjones
            logMetacat.warn("Could not parse toDate: " + e.getMessage());
433
        }
434 6270 leinfelder
        try {
435 6756 cjones
            String eventS = params.get("event")[0];
436 6270 leinfelder
            event = Event.convert(eventS);
437
        } catch (Exception e) {
438 6756 cjones
            logMetacat.warn("Could not parse event: " + e.getMessage());
439
        }
440 6272 leinfelder
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
441 6756 cjones
442 6270 leinfelder
        try {
443 6756 cjones
            start = Integer.parseInt(params.get("start")[0]);
444 6270 leinfelder
        } catch (Exception e) {
445 6756 cjones
            logMetacat.warn("Could not parse start: " + e.getMessage());
446
        }
447 6270 leinfelder
        try {
448 6756 cjones
            count = Integer.parseInt(params.get("count")[0]);
449 6270 leinfelder
        } catch (Exception e) {
450 6756 cjones
            logMetacat.warn("Could not parse count: " + e.getMessage());
451
        }
452
453 6272 leinfelder
        logMetacat.debug("calling getLogRecords");
454 6756 cjones
        Log log = CNodeService.getInstance(request).getLogRecords(session,
455
                fromDate, toDate, event, start, count);
456
457 6270 leinfelder
        OutputStream out = response.getOutputStream();
458
        response.setStatus(200);
459
        response.setContentType("text/xml");
460 6756 cjones
461 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(log, out);
462 6756 cjones
463 6253 leinfelder
    }
464
465
    /**
466
     * Implements REST version of DataONE CRUD API --> get
467 6756 cjones
     *
468
     * @param guid
469
     *            ID of data object to be read
470
     * @throws NotImplemented
471
     * @throws InvalidRequest
472
     * @throws NotFound
473
     * @throws NotAuthorized
474
     * @throws ServiceFailure
475
     * @throws InvalidToken
476
     * @throws IOException
477 6253 leinfelder
     */
478 6756 cjones
    protected void getObject(String guid) throws InvalidToken, ServiceFailure,
479
            NotAuthorized, NotFound, InvalidRequest, NotImplemented,
480
            IOException {
481 6270 leinfelder
482 6280 leinfelder
        Identifier id = new Identifier();
483
        id.setValue(guid);
484 6756 cjones
485
        SystemMetadata sm = CNodeService.getInstance(request)
486
                .getSystemMetadata(session, id);
487
488
        // set the content type
489
        if (sm.getFormatId()
490
                .getValue()
491
                .trim()
492
                .equals(ObjectFormatCache.getInstance().getFormat("text/csv")
493
                        .getFormatId().getValue())) {
494 6280 leinfelder
            response.setContentType("text/csv");
495 6756 cjones
            response.setHeader("Content-Disposition",
496
                    "inline; filename=" + id.getValue() + ".csv");
497
        } else if (sm
498
                .getFormatId()
499
                .getValue()
500
                .trim()
501
                .equals(ObjectFormatCache.getInstance().getFormat("text/plain")
502
                        .getFormatId().getValue())) {
503 6280 leinfelder
            response.setContentType("text/plain");
504 6756 cjones
            response.setHeader("Content-Disposition",
505
                    "inline; filename=" + id.getValue() + ".txt");
506
        } else if (sm
507
                .getFormatId()
508
                .getValue()
509
                .trim()
510
                .equals(ObjectFormatCache.getInstance()
511
                        .getFormat("application/octet-stream").getFormatId()
512
                        .getValue())) {
513 6280 leinfelder
            response.setContentType("application/octet-stream");
514 6756 cjones
        } else {
515 6280 leinfelder
            response.setContentType("text/xml");
516 6756 cjones
            response.setHeader("Content-Disposition",
517
                    "inline; filename=" + id.getValue() + ".xml");
518 6280 leinfelder
        }
519 6756 cjones
520 6542 leinfelder
        InputStream data = CNodeService.getInstance(request).get(session, id);
521 6756 cjones
522 6280 leinfelder
        OutputStream out = response.getOutputStream();
523
        response.setStatus(200);
524
        IOUtils.copyLarge(data, out);
525 6756 cjones
526 6253 leinfelder
    }
527
528
    /**
529
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
530 6756 cjones
     *
531
     * @param guid
532
     *            ID of data object to be read
533
     * @throws NotImplemented
534
     * @throws InvalidRequest
535
     * @throws NotFound
536
     * @throws NotAuthorized
537
     * @throws ServiceFailure
538
     * @throws InvalidToken
539
     * @throws IOException
540
     * @throws JiBXException
541 6253 leinfelder
     */
542 6756 cjones
    protected void getSystemMetadataObject(String guid) throws InvalidToken,
543
            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
544
            NotImplemented, IOException, JiBXException {
545 6270 leinfelder
546
        Identifier id = new Identifier();
547
        id.setValue(guid);
548 6756 cjones
        SystemMetadata sysmeta = CNodeService.getInstance(request)
549
                .getSystemMetadata(session, id);
550
551 6270 leinfelder
        response.setContentType("text/xml");
552
        response.setStatus(200);
553
        OutputStream out = response.getOutputStream();
554 6756 cjones
555 6270 leinfelder
        // Serialize and write it to the output stream
556 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
557 6756 cjones
    }
558
559 6253 leinfelder
    /**
560 6756 cjones
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler >
561
     * handleInsertOrUpdateAction
562 6253 leinfelder
     *
563 6756 cjones
     * @param guid
564
     *            - ID of data object to be inserted or updated. If action is
565
     *            update, the pid is the existing pid. If insert, the pid is the
566
     *            new one
567
     * @throws InvalidRequest
568
     * @throws ServiceFailure
569
     * @throws IdentifierNotUnique
570
     * @throws JiBXException
571
     * @throws NotImplemented
572
     * @throws InvalidSystemMetadata
573
     * @throws InsufficientResources
574
     * @throws UnsupportedType
575
     * @throws NotAuthorized
576
     * @throws InvalidToken
577
     * @throws IOException
578
     * @throws IllegalAccessException
579
     * @throws InstantiationException
580 6253 leinfelder
     */
581 6756 cjones
    protected void putObject(String pid, String action) throws ServiceFailure,
582
            InvalidRequest, IdentifierNotUnique, JiBXException, InvalidToken,
583
            NotAuthorized, UnsupportedType, InsufficientResources,
584
            InvalidSystemMetadata, NotImplemented, IOException,
585
            InstantiationException, IllegalAccessException {
586 6253 leinfelder
        logMetacat.debug("Entering putObject: " + pid + "/" + action);
587 6756 cjones
588 6269 leinfelder
        // Read the incoming data from its Mime Multipart encoding
589 6756 cjones
        Map<String, File> files = collectMultipartFiles();
590 6269 leinfelder
        InputStream object = null;
591
        InputStream sysmeta = null;
592 6253 leinfelder
593 6269 leinfelder
        File smFile = files.get("sysmeta");
594
        sysmeta = new FileInputStream(smFile);
595
        File objFile = files.get("object");
596
        object = new FileInputStream(objFile);
597 6253 leinfelder
598 6756 cjones
        if (action.equals(FUNCTION_NAME_INSERT)) { // handle inserts
599
600 6269 leinfelder
            logMetacat.debug("Commence creation...");
601 6756 cjones
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(
602
                    SystemMetadata.class, sysmeta);
603 6253 leinfelder
604 6269 leinfelder
            Identifier id = new Identifier();
605
            id.setValue(pid);
606
            logMetacat.debug("creating object with pid " + id.getValue());
607 6756 cjones
            Identifier rId = CNodeService.getInstance(request).create(session,
608
                    id, object, smd);
609
610 6269 leinfelder
            OutputStream out = response.getOutputStream();
611
            response.setStatus(200);
612
            response.setContentType("text/xml");
613 6756 cjones
614 6367 leinfelder
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
615 6756 cjones
616 6269 leinfelder
        } else {
617
            throw new InvalidRequest("1000", "Operation must be create.");
618 6253 leinfelder
        }
619
    }
620
621
    /**
622
     * List the object formats registered with the system
623 6756 cjones
     *
624
     * @throws NotImplemented
625
     * @throws InsufficientResources
626
     * @throws NotFound
627
     * @throws ServiceFailure
628
     * @throws InvalidRequest
629
     * @throws IOException
630
     * @throws JiBXException
631 6253 leinfelder
     */
632 6756 cjones
    private void listFormats() throws InvalidRequest, ServiceFailure, NotFound,
633
            InsufficientResources, NotImplemented, IOException, JiBXException {
634
        logMetacat.debug("Entering listFormats()");
635 6270 leinfelder
636 6756 cjones
        ObjectFormatList objectFormatList = CNodeService.getInstance(request)
637
                .listFormats();
638
        // get the response output stream
639
        OutputStream out = response.getOutputStream();
640
        response.setStatus(200);
641
        response.setContentType("text/xml");
642
643
        // style the object with a processing directive
644
        String stylesheet = null;
645
        try {
646
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
647
        } catch (PropertyNotFoundException e) {
648
            logMetacat.warn("Could not locate DataONE types XSLT: "
649
                    + e.getMessage());
650
        }
651
652
        TypeMarshaller.marshalTypeToOutputStream(objectFormatList, out,
653
                stylesheet);
654
655 6253 leinfelder
    }
656
657 6756 cjones
    /**
658 6253 leinfelder
     * Return the requested object format
659
     *
660 6756 cjones
     * @param fmtidStr
661
     *            the requested format identifier as a string
662
     * @throws NotImplemented
663
     * @throws InsufficientResources
664
     * @throws NotFound
665
     * @throws ServiceFailure
666
     * @throws InvalidRequest
667
     * @throws IOException
668
     * @throws JiBXException
669 6253 leinfelder
     */
670 6756 cjones
    private void getFormat(String fmtidStr) throws InvalidRequest,
671
            ServiceFailure, NotFound, InsufficientResources, NotImplemented,
672
            IOException, JiBXException {
673
        logMetacat.debug("Entering listFormats()");
674
675
        ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
676
        fmtid.setValue(fmtidStr);
677
678
        // get the specified object format
679
        ObjectFormat objectFormat = CNodeService.getInstance(request)
680
                .getFormat(fmtid);
681
682
        OutputStream out = response.getOutputStream();
683
        response.setStatus(200);
684
        response.setContentType("text/xml");
685
686
        TypeMarshaller.marshalTypeToOutputStream(objectFormat, out);
687
688 6253 leinfelder
    }
689 6756 cjones
690 6253 leinfelder
    /**
691
     * Reserve the given Identifier
692 6756 cjones
     *
693 6253 leinfelder
     * @throws InvalidToken
694
     * @throws ServiceFailure
695
     * @throws NotAuthorized
696
     * @throws IdentifierNotUnique
697
     * @throws NotImplemented
698
     * @throws InvalidRequest
699 6756 cjones
     * @throws IOException
700
     * @throws JiBXException
701 6253 leinfelder
     */
702 6756 cjones
    private void reserve() throws InvalidToken, ServiceFailure, NotAuthorized,
703
            IdentifierNotUnique, NotImplemented, InvalidRequest, IOException,
704
            JiBXException {
705
        Identifier pid = null;
706
        String scope = null;
707
        String format = null;
708
        // gather the params
709
        try {
710
            String id = params.get("pid")[0];
711
            pid = new Identifier();
712
            pid.setValue(id);
713
        } catch (Exception e) {
714
            logMetacat.warn("pid not specified");
715
        }
716
        try {
717
            scope = params.get("scope")[0];
718
        } catch (Exception e) {
719
            logMetacat.warn("pid not specified");
720
        }
721
        try {
722
            format = params.get("format")[0];
723
        } catch (Exception e) {
724
            logMetacat.warn("pid not specified");
725
        }
726
        // call the implementation
727
        Identifier resultPid = CNodeService.getInstance(request)
728
                .reserveIdentifier(session, pid);
729
        OutputStream out = response.getOutputStream();
730
        response.setStatus(200);
731
        response.setContentType("text/xml");
732
        // send back the reserved pid
733
        TypeMarshaller.marshalTypeToOutputStream(resultPid, out);
734 6253 leinfelder
    }
735 6756 cjones
736 6270 leinfelder
    /**
737
     *
738
     * @param id
739
     * @throws InvalidRequest
740
     * @throws InvalidToken
741
     * @throws ServiceFailure
742
     * @throws NotAuthorized
743
     * @throws NotFound
744
     * @throws NotImplemented
745
     * @throws IOException
746 6756 cjones
     * @throws JiBXException
747 6270 leinfelder
     */
748 6756 cjones
    private void resolve(String id) throws InvalidRequest, InvalidToken,
749
            ServiceFailure, NotAuthorized, NotFound, NotImplemented,
750
            IOException, JiBXException {
751
        Identifier pid = new Identifier();
752
        pid.setValue(id);
753
        ObjectLocationList locationList = CNodeService.getInstance(request)
754
                .resolve(session, pid);
755
        OutputStream out = response.getOutputStream();
756
        response.setStatus(200);
757
        response.setContentType("text/xml");
758
        TypeMarshaller.marshalTypeToOutputStream(locationList, out);
759
760 6253 leinfelder
    }
761
762 6270 leinfelder
    /**
763
     * Assert that a relationship exists between two resources
764 6756 cjones
     *
765 6270 leinfelder
     * @param id
766
     * @return
767
     * @throws InvalidToken
768
     * @throws ServiceFailure
769
     * @throws NotAuthorized
770
     * @throws NotFound
771
     * @throws InvalidRequest
772
     * @throws NotImplemented
773
     */
774 6756 cjones
    private boolean assertRelation(String id) throws InvalidToken,
775
            ServiceFailure, NotAuthorized, NotFound, InvalidRequest,
776
            NotImplemented {
777
        Identifier pidOfSubject = new Identifier();
778
        pidOfSubject.setValue(id);
779
        String relationship = null;
780
        try {
781
            relationship = params.get("relationship")[0];
782
        } catch (Exception e) {
783
            logMetacat.warn("relationship not specified");
784
        }
785
        Identifier pidOfObject = new Identifier();
786
        try {
787
            String objPid = params.get("pidOfObject")[0];
788
            pidOfObject.setValue(objPid);
789
        } catch (Exception e) {
790
            logMetacat.warn("pidOfObject not specified");
791
        }
792
        boolean result = CNodeService.getInstance(request).assertRelation(
793
                session, pidOfSubject, relationship, pidOfObject);
794
        response.setStatus(200);
795
        response.setContentType("text/xml");
796
        return result;
797 6253 leinfelder
    }
798 6756 cjones
799 6270 leinfelder
    /**
800
     * Set the owner of a resource
801 6756 cjones
     *
802 6270 leinfelder
     * @param id
803
     * @throws JiBXException
804
     * @throws InvalidToken
805
     * @throws ServiceFailure
806
     * @throws NotFound
807
     * @throws NotAuthorized
808
     * @throws NotImplemented
809
     * @throws InvalidRequest
810
     * @throws IOException
811 6756 cjones
     * @throws IllegalAccessException
812
     * @throws InstantiationException
813 6270 leinfelder
     */
814 6756 cjones
    private void owner(String id) throws JiBXException, InvalidToken,
815
            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
816
            InvalidRequest, IOException, InstantiationException,
817
            IllegalAccessException {
818
819 6592 cjones
        Identifier pid = new Identifier();
820 6756 cjones
        pid.setValue(id);
821 6592 cjones
822
        long serialVersion = 0L;
823
        String serialVersionStr = null;
824 6756 cjones
825 6592 cjones
        // get the serialVersion
826
        try {
827
            serialVersionStr = params.get("serialVersion")[0];
828
            serialVersion = new Long(serialVersionStr).longValue();
829 6756 cjones
830 6592 cjones
        } catch (NullPointerException e) {
831
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
832
            logMetacat.error(msg);
833
            throw new InvalidRequest("4442", msg);
834 6756 cjones
835
        }
836
837
        // get the subject
838
        String subjectStr = params.get("subject")[0];
839
        Subject subject = TypeMarshaller.unmarshalTypeFromStream(Subject.class,
840
                new ByteArrayInputStream(subjectStr.getBytes("UTF-8")));
841
842
        Identifier retPid = CNodeService.getInstance(request).setOwner(session,
843
                pid, subject, serialVersion);
844
        OutputStream out = response.getOutputStream();
845
        response.setStatus(200);
846
        response.setContentType("text/xml");
847
        TypeMarshaller.marshalTypeToOutputStream(retPid, out);
848 6253 leinfelder
    }
849 6756 cjones
850 6270 leinfelder
    /**
851
     * Processes the authorization check for given id
852 6756 cjones
     *
853 6270 leinfelder
     * @param id
854
     * @return
855
     * @throws ServiceFailure
856
     * @throws InvalidToken
857
     * @throws NotFound
858
     * @throws NotAuthorized
859
     * @throws NotImplemented
860
     * @throws InvalidRequest
861
     */
862 6756 cjones
    private boolean isAuthorized(String id) throws ServiceFailure,
863
            InvalidToken, NotFound, NotAuthorized, NotImplemented,
864
            InvalidRequest {
865
        Identifier pid = new Identifier();
866
        pid.setValue(id);
867
        String permission = params.get("action")[0];
868
        boolean result = CNodeService.getInstance(request).isAuthorized(
869
                session, pid, Permission.convert(permission));
870
        response.setStatus(200);
871
        response.setContentType("text/xml");
872
        return result;
873 6253 leinfelder
    }
874 6756 cjones
875 6253 leinfelder
    /**
876
     * Register System Metadata without data or metadata object
877 6756 cjones
     *
878
     * @param pid
879
     *            identifier for System Metadata entry
880
     * @throws JiBXException
881
     * @throws FileUploadException
882
     * @throws IOException
883
     * @throws InvalidRequest
884
     * @throws ServiceFailure
885
     * @throws InvalidSystemMetadata
886
     * @throws NotAuthorized
887
     * @throws NotImplemented
888
     * @throws IllegalAccessException
889
     * @throws InstantiationException
890 6253 leinfelder
     */
891 6756 cjones
    protected Identifier registerSystemMetadata(String pid)
892
            throws ServiceFailure, InvalidRequest, IOException,
893
            FileUploadException, JiBXException, NotImplemented, NotAuthorized,
894
            InvalidSystemMetadata, InstantiationException,
895
            IllegalAccessException {
896
        logMetacat.debug("Entering registerSystemMetadata: " + pid);
897 6253 leinfelder
898 6756 cjones
        // get the system metadata from the request
899
        SystemMetadata systemMetadata = collectSystemMetadata();
900 6253 leinfelder
901 6756 cjones
        Identifier guid = new Identifier();
902
        guid.setValue(pid);
903
        logMetacat.debug("registering system metadata with pid "
904
                + guid.getValue());
905
        Identifier retGuid = CNodeService.getInstance(request)
906
                .registerSystemMetadata(session, guid, systemMetadata);
907
908
        response.setStatus(200);
909
        response.setContentType("text/xml");
910
        return retGuid;
911
912
    }
913
914 6268 leinfelder
    /**
915
     * set the access perms on a document
916 6756 cjones
     *
917
     * @throws JiBXException
918
     * @throws InvalidRequest
919
     * @throws NotImplemented
920
     * @throws NotAuthorized
921
     * @throws NotFound
922
     * @throws ServiceFailure
923
     * @throws InvalidToken
924
     * @throws IllegalAccessException
925
     * @throws InstantiationException
926
     * @throws IOException
927
     * @throws SAXException
928
     * @throws ParserConfigurationException
929 6268 leinfelder
     */
930 6756 cjones
    protected void setAccess(String pid) throws JiBXException, InvalidToken,
931
            ServiceFailure, NotFound, NotAuthorized, NotImplemented,
932
            InvalidRequest, IOException, InstantiationException,
933
            IllegalAccessException, ParserConfigurationException, SAXException {
934 6270 leinfelder
935 6592 cjones
        long serialVersion = 0L;
936
        String serialVersionStr = null;
937 6756 cjones
938 6592 cjones
        // get the serialVersion
939
        try {
940
            serialVersionStr = params.get("serialVersion")[0];
941
            serialVersion = new Long(serialVersionStr).longValue();
942 6756 cjones
943 6592 cjones
        } catch (NullPointerException e) {
944
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
945
            logMetacat.error(msg);
946
            throw new InvalidRequest("4402", msg);
947 6756 cjones
948 6592 cjones
        }
949 6756 cjones
950 6270 leinfelder
        Identifier id = new Identifier();
951 6514 leinfelder
        id.setValue(pid);
952 6756 cjones
953 6514 leinfelder
        AccessPolicy accessPolicy = collectAccessPolicy();
954 6756 cjones
        CNodeService.getInstance(request).setAccessPolicy(session, id,
955
                accessPolicy, serialVersion);
956 6270 leinfelder
957 6268 leinfelder
    }
958 6756 cjones
959 6268 leinfelder
    /**
960 6756 cjones
     * List the objects
961
     *
962
     * @throws NotImplemented
963
     * @throws InvalidRequest
964
     * @throws NotAuthorized
965
     * @throws ServiceFailure
966
     * @throws InvalidToken
967
     * @throws NotFound
968
     * @throws IOException
969 6622 leinfelder
     * @throws JiBXException
970 6268 leinfelder
     * @throws Exception
971
     */
972 6756 cjones
    private void listObjects() throws InvalidToken, ServiceFailure,
973
            NotAuthorized, InvalidRequest, NotImplemented, NotFound,
974
            IOException, JiBXException {
975 6622 leinfelder
976 6756 cjones
        Date startTime = null;
977
        Date endTime = null;
978
        ObjectFormat objectFormat = null;
979
        boolean replicaStatus = false;
980
        int start = 0;
981
        int count = -1;
982
        Enumeration<String> paramlist = request.getParameterNames();
983
        while (paramlist.hasMoreElements()) {
984
            // parse the params and make the call
985
            String name = paramlist.nextElement();
986
            String[] value = request.getParameterValues(name);
987 6622 leinfelder
988 6756 cjones
            if (name.equals("startTime") && value != null) {
989
                try {
990
                    startTime = DateTimeMarshaller
991
                            .deserializeDateToUTC(value[0]);
992
                } catch (Exception e) {
993
                    // if we can't parse it, just don't use the startTime param
994
                    logMetacat.warn("Could not parse startTime: " + value[0]);
995
                    startTime = null;
996
                }
997
            } else if (name.equals("endTime") && value != null) {
998
                try {
999
                    endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
1000
                } catch (Exception e) {
1001
                    // if we can't parse it, just don't use the endTime param
1002
                    logMetacat.warn("Could not parse endTime: " + value[0]);
1003
                    endTime = null;
1004
                }
1005
            } else if (name.equals("objectFormat") && value != null) {
1006
                objectFormat = ObjectFormatCache.getInstance().getFormat(
1007
                        value[0]);
1008
            } else if (name.equals("replicaStatus") && value != null) {
1009
                replicaStatus = Boolean.parseBoolean(value[0]);
1010
            } else if (name.equals("start") && value != null) {
1011
                start = Integer.valueOf(value[0]);
1012
            } else if (name.equals("count") && value != null) {
1013
                count = Integer.valueOf(value[0]);
1014
            }
1015
        }
1016
        // make the call
1017
        logMetacat.debug("session: " + session + " startTime: " + startTime
1018
                + " endtime: " + endTime + " objectFormat: " + objectFormat
1019
                + " replicaStatus: " + replicaStatus + " start: " + start
1020
                + " count: " + count);
1021 6622 leinfelder
1022 6756 cjones
        ObjectFormatIdentifier fmtid = null;
1023
        if (objectFormat != null) {
1024
            fmtid = objectFormat.getFormatId();
1025
        }
1026 6622 leinfelder
1027 6756 cjones
        // get the list
1028
        ObjectList ol = CNodeService.getInstance(request).listObjects(session,
1029
                startTime, endTime, fmtid, replicaStatus, start, count);
1030
1031
        // send it
1032
        OutputStream out = response.getOutputStream();
1033
        response.setStatus(200);
1034
        response.setContentType("text/xml");
1035
1036
        // style the object with a processing directive
1037
        String stylesheet = null;
1038
        try {
1039
            stylesheet = PropertyService.getProperty("dataone.types.xsl");
1040
        } catch (PropertyNotFoundException e) {
1041
            logMetacat.warn("Could not locate DataONE types XSLT: "
1042
                    + e.getMessage());
1043
        }
1044
1045
        // Serialize and write it to the output stream
1046
        TypeMarshaller.marshalTypeToOutputStream(ol, out, stylesheet);
1047
    }
1048
1049 6592 cjones
    /**
1050
     * Pass the request to get node replication authorization to CNodeService
1051
     *
1052 6756 cjones
     * @param pid
1053
     *            the identifier of the object to get authorization to replicate
1054 6592 cjones
     *
1055
     * @throws NotImplemented
1056
     * @throws NotAuthorized
1057
     * @throws InvalidToken
1058
     * @throws ServiceFailure
1059
     * @throws NotFound
1060
     * @throws InvalidRequest
1061
     */
1062 6756 cjones
    public boolean isNodeAuthorized(String pid) throws NotImplemented,
1063
            NotAuthorized, InvalidToken, ServiceFailure, NotFound,
1064
            InvalidRequest {
1065
1066 6592 cjones
        boolean result = false;
1067
        Subject targetNodeSubject = new Subject();
1068
        String nodeSubject = null;
1069
        Permission permission = null;
1070
        String replPermission = null;
1071 6756 cjones
1072 6592 cjones
        // get the pid
1073
        Identifier identifier = new Identifier();
1074
        identifier.setValue(pid);
1075 6756 cjones
1076 6592 cjones
        // get the target node subject
1077
        try {
1078
            nodeSubject = params.get("targetNodeSubject")[0];
1079
            targetNodeSubject.setValue(nodeSubject);
1080 6756 cjones
1081 6592 cjones
        } catch (NullPointerException e) {
1082
            String msg = "The 'targetNodeSubject' must be provided as a parameter and was not.";
1083
            logMetacat.error(msg);
1084
            throw new InvalidRequest("4873", msg);
1085 6756 cjones
1086 6592 cjones
        }
1087 6756 cjones
1088 6592 cjones
        // get the permission
1089
        try {
1090
            replPermission = params.get("replicatePermission")[0];
1091
            permission = Permission.convert(replPermission);
1092 6268 leinfelder
1093 6592 cjones
        } catch (NullPointerException e) {
1094
            String msg = "The 'replicatePermission' must be provided as a parameter and was not.";
1095
            logMetacat.error(msg);
1096
            throw new InvalidRequest("4873", msg);
1097
1098
        }
1099 6756 cjones
1100
        result = CNodeService.getInstance(request).isNodeAuthorized(session,
1101
                targetNodeSubject, identifier, permission);
1102
1103 6592 cjones
        response.setStatus(200);
1104
        response.setContentType("text/xml");
1105
        return result;
1106 6756 cjones
1107 6592 cjones
    }
1108 6756 cjones
1109 6592 cjones
    /**
1110
     * Pass the request to set the replication policy to CNodeService
1111
     *
1112 6756 cjones
     * @param pid
1113
     *            the identifier of the object to set the replication policy on
1114 6592 cjones
     *
1115
     * @throws NotImplemented
1116
     * @throws NotFound
1117
     * @throws NotAuthorized
1118
     * @throws ServiceFailure
1119
     * @throws InvalidRequest
1120
     * @throws InvalidToken
1121
     * @throws IOException
1122
     * @throws InstantiationException
1123
     * @throws IllegalAccessException
1124
     * @throws JiBXException
1125
     */
1126 6756 cjones
    public boolean setReplicationPolicy(String pid) throws NotImplemented,
1127
            NotFound, NotAuthorized, ServiceFailure, InvalidRequest,
1128
            InvalidToken, IOException, InstantiationException,
1129
            IllegalAccessException, JiBXException {
1130
1131 6592 cjones
        boolean result = false;
1132
        ReplicationPolicy policy = null;
1133
        long serialVersion = 0L;
1134
        String serialVersionStr = null;
1135 6756 cjones
1136 6592 cjones
        Identifier identifier = new Identifier();
1137
        identifier.setValue(pid);
1138 6756 cjones
1139 6634 cjones
        policy = collectReplicationPolicy();
1140
1141 6592 cjones
        // get the serialVersion
1142
        try {
1143 6603 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1144 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1145 6756 cjones
1146 6592 cjones
        } catch (NullPointerException e) {
1147
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1148
            logMetacat.error(msg);
1149
            throw new InvalidRequest("4883", msg);
1150 6756 cjones
1151 6592 cjones
        }
1152 6756 cjones
        result = CNodeService.getInstance(request).setReplicationPolicy(
1153
                session, identifier, policy, serialVersion);
1154 6592 cjones
        response.setStatus(200);
1155
        response.setContentType("text/xml");
1156
        return result;
1157 6756 cjones
1158 6592 cjones
    }
1159 6756 cjones
1160 6592 cjones
    /**
1161
     * Pass the request to set the replication status to CNodeService
1162
     *
1163 6756 cjones
     * @param pid
1164
     *            the identifier of the object to set the replication status on
1165 6592 cjones
     *
1166
     * @throws ServiceFailure
1167
     * @throws NotImplemented
1168
     * @throws InvalidToken
1169
     * @throws NotAuthorized
1170
     * @throws InvalidRequest
1171
     * @throws NotFound
1172
     */
1173 6756 cjones
    public boolean setReplicationStatus(String pid) throws ServiceFailure,
1174
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1175
            NotFound {
1176 6592 cjones
1177 6634 cjones
        File tmpDir = getTempDirectory();
1178
        MultipartRequest mr = null;
1179 6592 cjones
        boolean result = false;
1180
        Identifier identifier = new Identifier();
1181
        identifier.setValue(pid);
1182
        long serialVersion = 0L;
1183
        String serialVersionStr = null;
1184
        ReplicationStatus status = null;
1185
        String replicationStatus = null;
1186
        NodeReference targetNodeRef = null;
1187
        String targetNode = null;
1188 6756 cjones
1189 6634 cjones
        // Parse the params out of the multipart form data
1190
        // Read the incoming data from its Mime Multipart encoding
1191 6756 cjones
        logMetacat
1192
                .debug("Parsing ReplicaStatus from the mime multipart entity");
1193 6634 cjones
1194
        // handle MMP inputs
1195 6756 cjones
        MultipartRequestResolver mrr = new MultipartRequestResolver(
1196
                tmpDir.getAbsolutePath(), 1000000000, 0);
1197
1198 6634 cjones
        try {
1199
            mr = mrr.resolveMultipart(request);
1200
            multipartparams = mr.getMultipartParameters();
1201
            logMetacat.debug("Resolved the ReplicaStatus multipart request.");
1202 6756 cjones
1203 6634 cjones
        } catch (IOException e) {
1204 6756 cjones
            throw new ServiceFailure("4852",
1205
                    "Couldn't resolve the multipart request: " + e.getMessage());
1206
1207 6634 cjones
        } catch (FileUploadException e) {
1208 6756 cjones
            throw new ServiceFailure("4852",
1209
                    "Couldn't resolve the multipart request: " + e.getMessage());
1210
1211 6634 cjones
        } catch (Exception e) {
1212 6756 cjones
            throw new ServiceFailure("4852",
1213
                    "Couldn't resolve the multipart request: " + e.getMessage());
1214
1215 6634 cjones
        }
1216
1217 6592 cjones
        // get the serialVersion
1218
        try {
1219 6603 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1220 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1221 6756 cjones
1222 6642 cjones
        } catch (NumberFormatException nfe) {
1223
            String msg = "The 'serialVersion' must be a positive integer and was not.";
1224 6592 cjones
            logMetacat.error(msg);
1225
            throw new InvalidRequest("4730", msg);
1226 6756 cjones
1227 6642 cjones
        } catch (NullPointerException e) {
1228 6756 cjones
            logMetacat
1229
                    .debug("The 'serialVersion' parameter was not found in the "
1230
                            + "multipartparams map.  Trying the params map.");
1231 6642 cjones
            try {
1232
                serialVersionStr = params.get("serialVersion")[0];
1233
                serialVersion = new Long(serialVersionStr).longValue();
1234 6756 cjones
1235 6642 cjones
            } catch (NumberFormatException e1) {
1236
                String msg = "The 'serialVersion' must be a positive integer and was not.";
1237
                logMetacat.error(msg);
1238
                throw new InvalidRequest("4730", msg);
1239 6756 cjones
1240 6642 cjones
            } catch (NullPointerException npe) {
1241
                String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1242
                logMetacat.error(msg);
1243
                throw new InvalidRequest("4730", msg);
1244
1245
            }
1246 6756 cjones
1247 6592 cjones
        }
1248 6756 cjones
1249 6592 cjones
        // get the replication status param
1250
        try {
1251 6643 cjones
            replicationStatus = multipartparams.get("status").get(0);
1252 6592 cjones
            status = ReplicationStatus.convert(replicationStatus);
1253 6677 cjones
1254 6642 cjones
        } catch (NullPointerException npe) {
1255
1256 6756 cjones
            logMetacat.debug("The 'status' parameter was not found in the "
1257
                    + "multipartparams map.  Trying the params map.");
1258
1259 6642 cjones
            try {
1260 6643 cjones
                replicationStatus = params.get("status")[0];
1261 6756 cjones
                status = ReplicationStatus.convert(replicationStatus
1262
                        .toLowerCase());
1263
1264 6642 cjones
            } catch (Exception e) {
1265 6643 cjones
                String msg = "The 'status' must be provided as a parameter and was not.";
1266 6642 cjones
                logMetacat.error(msg);
1267
                throw new InvalidRequest("4730", msg);
1268 6756 cjones
1269 6642 cjones
            }
1270 6756 cjones
1271 6592 cjones
        }
1272 6756 cjones
1273 6592 cjones
        // get the target node reference param
1274 6642 cjones
        try {
1275
            targetNode = multipartparams.get("nodeRef").get(0);
1276
            targetNodeRef = new NodeReference();
1277
            targetNodeRef.setValue(targetNode);
1278 6756 cjones
1279 6642 cjones
        } catch (NullPointerException e) {
1280 6756 cjones
            logMetacat.debug("The 'nodeRef' parameter was not found in the "
1281
                    + "multipartparams map.  Trying the params map.");
1282
1283 6642 cjones
            try {
1284
                targetNode = params.get("nodeRef")[0];
1285
                targetNodeRef = new NodeReference();
1286
                targetNodeRef.setValue(targetNode);
1287 6756 cjones
1288 6642 cjones
            } catch (Exception e1) {
1289
                String msg = "The 'nodeRef' must be provided as a parameter and was not.";
1290
                logMetacat.error(msg);
1291
                throw new InvalidRequest("4730", msg);
1292 6756 cjones
1293 6642 cjones
            }
1294 6756 cjones
1295 6642 cjones
        }
1296 6756 cjones
1297
        result = CNodeService.getInstance(request).setReplicationStatus(
1298
                session, identifier, targetNodeRef, status, serialVersion);
1299 6592 cjones
        response.setStatus(200);
1300
        response.setContentType("text/xml");
1301
        return result;
1302 6756 cjones
1303 6592 cjones
    }
1304 6756 cjones
1305 6592 cjones
    /**
1306
     * Pass the request to update the replication metadata to CNodeService
1307
     *
1308 6756 cjones
     * @param pid
1309
     *            the identifier of the object to update the replication
1310
     *            metadata on
1311 6592 cjones
     *
1312
     * @throws ServiceFailure
1313
     * @throws NotImplemented
1314
     * @throws InvalidToken
1315
     * @throws NotAuthorized
1316
     * @throws InvalidRequest
1317
     * @throws NotFound
1318
     */
1319 6756 cjones
    public boolean updateReplicationMetadata(String pid) throws ServiceFailure,
1320
            NotImplemented, InvalidToken, NotAuthorized, InvalidRequest,
1321
            NotFound {
1322 6592 cjones
1323
        boolean result = false;
1324
        long serialVersion = 0L;
1325
        String serialVersionStr = null;
1326
        Replica replica = null;
1327
        Identifier identifier = new Identifier();
1328
        identifier.setValue(pid);
1329
1330 6634 cjones
        replica = collectReplicaMetadata();
1331 6756 cjones
1332 6592 cjones
        // get the serialVersion
1333
        try {
1334 6603 cjones
            serialVersionStr = multipartparams.get("serialVersion").get(0);
1335 6592 cjones
            serialVersion = new Long(serialVersionStr).longValue();
1336 6756 cjones
1337 6592 cjones
        } catch (NullPointerException e) {
1338
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
1339
            logMetacat.error(msg);
1340
            throw new InvalidRequest("4853", msg);
1341 6756 cjones
1342 6592 cjones
        }
1343
1344 6756 cjones
        result = CNodeService.getInstance(request).updateReplicationMetadata(
1345
                session, identifier, replica, serialVersion);
1346 6592 cjones
        response.setStatus(200);
1347
        response.setContentType("text/xml");
1348
        return result;
1349
1350
    }
1351
1352 6253 leinfelder
}