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