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