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