Project

General

Profile

1 6264 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 6264 leinfelder
25
import java.io.File;
26
import java.io.FileInputStream;
27 9122 tao
import java.io.FileNotFoundException;
28 6264 leinfelder
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.util.Date;
32
import java.util.Enumeration;
33 9235 leinfelder
import java.util.Iterator;
34 6264 leinfelder
import java.util.Map;
35 6679 leinfelder
import java.util.concurrent.ExecutorService;
36
import java.util.concurrent.Executors;
37 6264 leinfelder
38
import javax.servlet.ServletContext;
39
import javax.servlet.http.HttpServletRequest;
40
import javax.servlet.http.HttpServletResponse;
41 6472 leinfelder
import javax.xml.parsers.ParserConfigurationException;
42 6264 leinfelder
43 6273 leinfelder
import org.apache.commons.fileupload.FileUploadException;
44 6264 leinfelder
import org.apache.commons.io.IOUtils;
45
import org.apache.log4j.Logger;
46 9235 leinfelder
import org.dataone.client.v2.formats.ObjectFormatCache;
47 8810 leinfelder
import org.dataone.client.v2.formats.ObjectFormatInfo;
48 6472 leinfelder
import org.dataone.mimemultipart.MultipartRequest;
49
import org.dataone.mimemultipart.MultipartRequestResolver;
50 8874 leinfelder
import org.dataone.portal.TokenGenerator;
51 6264 leinfelder
import org.dataone.service.exceptions.BaseException;
52
import org.dataone.service.exceptions.IdentifierNotUnique;
53
import org.dataone.service.exceptions.InsufficientResources;
54
import org.dataone.service.exceptions.InvalidRequest;
55
import org.dataone.service.exceptions.InvalidSystemMetadata;
56
import org.dataone.service.exceptions.InvalidToken;
57
import org.dataone.service.exceptions.NotAuthorized;
58
import org.dataone.service.exceptions.NotFound;
59
import org.dataone.service.exceptions.NotImplemented;
60
import org.dataone.service.exceptions.ServiceFailure;
61
import org.dataone.service.exceptions.SynchronizationFailed;
62
import org.dataone.service.exceptions.UnsupportedType;
63 6366 leinfelder
import org.dataone.service.types.v1.Checksum;
64
import org.dataone.service.types.v1.DescribeResponse;
65
import org.dataone.service.types.v1.Identifier;
66
import org.dataone.service.types.v1.NodeReference;
67
import org.dataone.service.types.v1.ObjectFormatIdentifier;
68
import org.dataone.service.types.v1.ObjectList;
69
import org.dataone.service.types.v1.Permission;
70 9009 leinfelder
import org.dataone.service.types.v1.Person;
71 9173 leinfelder
import org.dataone.service.types.v1.Subject;
72
import org.dataone.service.types.v1.SubjectInfo;
73 7417 leinfelder
import org.dataone.service.types.v1_1.QueryEngineDescription;
74
import org.dataone.service.types.v1_1.QueryEngineList;
75 8874 leinfelder
import org.dataone.service.types.v2.Log;
76 9235 leinfelder
import org.dataone.service.types.v2.MediaType;
77
import org.dataone.service.types.v2.MediaTypeProperty;
78 8874 leinfelder
import org.dataone.service.types.v2.Node;
79 9244 leinfelder
import org.dataone.service.types.v2.ObjectFormat;
80 9148 tao
import org.dataone.service.types.v2.OptionList;
81 8874 leinfelder
import org.dataone.service.types.v2.SystemMetadata;
82 7019 leinfelder
import org.dataone.service.util.Constants;
83 6469 leinfelder
import org.dataone.service.util.DateTimeMarshaller;
84 6472 leinfelder
import org.dataone.service.util.ExceptionHandler;
85 6367 leinfelder
import org.dataone.service.util.TypeMarshaller;
86 6264 leinfelder
import org.jibx.runtime.JiBXException;
87 6472 leinfelder
import org.xml.sax.SAXException;
88 6264 leinfelder
89 8874 leinfelder
import edu.ucsb.nceas.metacat.MetaCatServlet;
90 7757 leinfelder
import edu.ucsb.nceas.metacat.common.query.stream.ContentTypeInputStream;
91 6264 leinfelder
import edu.ucsb.nceas.metacat.dataone.MNodeService;
92 6994 leinfelder
import edu.ucsb.nceas.metacat.properties.PropertyService;
93 8810 leinfelder
import edu.ucsb.nceas.metacat.restservice.D1ResourceHandler;
94 8160 leinfelder
import edu.ucsb.nceas.metacat.util.DeleteOnCloseFileInputStream;
95 6994 leinfelder
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
96 6264 leinfelder
97
/**
98
 * MN REST service implementation handler
99
 *
100
 * ******************
101
 * MNCore -- DONE
102
 * 		ping() - GET /d1/mn/monitor/ping
103
 * 		log() - GET /d1/mn/log
104
 * 		**getObjectStatistics() - GET /d1/mn/monitor/object
105
 * 		getOperationsStatistics - GET /d1/mn/monitor/event
106
 * 		**getStatus - GET /d1/mn/monitor/status
107
 * 		getCapabilities() - GET /d1/mn/ and /d1/mn/node
108
 *
109
 * 	MNRead -- DONE
110
 * 		get() - GET /d1/mn/object/PID
111
 * 		getSystemMetadata() - GET /d1/mn/meta/PID
112
 * 		describe() - HEAD /d1/mn/object/PID
113
 * 		getChecksum() - GET /d1/mn/checksum/PID
114
 * 		listObjects() - GET /d1/mn/object
115
 * 		synchronizationFailed() - POST /d1/mn/error
116
 *
117
 * 	MNAuthorization -- DONE
118
 * 		isAuthorized() - GET /d1/mn/isAuthorized/PID
119
 * 		setAccessPolicy() - PUT /d1/mn/accessRules/PID
120
 *
121 6297 cjones
 * 	MNStorage - DONE
122 6264 leinfelder
 * 		create() - POST /d1/mn/object/PID
123
 * 		update() - PUT /d1/mn/object/PID
124
 * 		delete() - DELETE /d1/mn/object/PID
125 7153 leinfelder
 * 		archive() - PUT /d1/mn/archive/PID
126 9122 tao
 *      updateSystemMetadata() - PUT /d1/mn/meta
127 7153 leinfelder
128 6619 cjones
 *    systemMetadataChanged() - POST /dirtySystemMetadata/PID
129 6264 leinfelder
 *
130
 * 	MNReplication
131
 * 		replicate() - POST /d1/mn/replicate
132 6604 cjones
 *    getReplica() - GET /d1/mn/replica
133 6264 leinfelder
 *
134
 * ******************
135
 * @author leinfelder
136
 *
137
 */
138 7417 leinfelder
public class MNResourceHandler extends D1ResourceHandler {
139 6264 leinfelder
140
    // MN-specific API Resources
141
    protected static final String RESOURCE_MONITOR = "monitor";
142
    protected static final String RESOURCE_REPLICATE = "replicate";
143 6604 cjones
    protected static final String RESOURCE_REPLICAS = "replica";
144 6264 leinfelder
    protected static final String RESOURCE_NODE = "node";
145
    protected static final String RESOURCE_ERROR = "error";
146 6619 cjones
    protected static final String RESOURCE_META_CHANGED = "dirtySystemMetadata";
147 7441 leinfelder
    protected static final String RESOURCE_GENERATE_ID = "generate";
148 7864 leinfelder
    protected static final String RESOURCE_PUBLISH = "publish";
149 9301 tao
    protected static final String RESOURCE_PACKAGE = "packages";
150 8874 leinfelder
    protected static final String RESOURCE_TOKEN = "token";
151 9173 leinfelder
    protected static final String RESOURCE_WHOAMI = "whoami";
152 7441 leinfelder
153 7861 leinfelder
154 8874 leinfelder
155 7143 leinfelder
156
    // shared executor
157
	private static ExecutorService executor = null;
158 6264 leinfelder
159 7143 leinfelder
	static {
160
		// use a shared executor service with nThreads == one less than available processors
161
    	int availableProcessors = Runtime.getRuntime().availableProcessors();
162
        int nThreads = availableProcessors * 1;
163
        nThreads--;
164 7183 leinfelder
        nThreads = Math.max(1, nThreads);
165 7143 leinfelder
    	executor = Executors.newFixedThreadPool(nThreads);
166
	}
167
168 6264 leinfelder
    /**
169
     * Initializes new instance by setting servlet context,request and response
170
     * */
171
    public MNResourceHandler(ServletContext servletContext,
172
            HttpServletRequest request, HttpServletResponse response) {
173
    	super(servletContext, request, response);
174
        logMetacat = Logger.getLogger(MNResourceHandler.class);
175
    }
176 6994 leinfelder
177
    @Override
178
    protected boolean isD1Enabled() {
179
180
    	boolean enabled = false;
181
    	try {
182
			enabled = Boolean.parseBoolean(PropertyService.getProperty("dataone.mn.services.enabled"));
183
		} catch (PropertyNotFoundException e) {
184
			logMetacat.error("Could not check if DataONE is enabled: " + e.getMessage());
185
		}
186
187
    	return enabled;
188
    }
189 6264 leinfelder
190
    /**
191 6271 leinfelder
     * This function is called from REST API servlet and handles each request to the servlet
192 6264 leinfelder
     *
193
     * @param httpVerb (GET, POST, PUT or DELETE)
194
     */
195 6271 leinfelder
    @Override
196 6264 leinfelder
    public void handle(byte httpVerb) {
197 6271 leinfelder
    	// prepare the handler
198
    	super.handle(httpVerb);
199
200 6264 leinfelder
        try {
201 6994 leinfelder
202
        	// only service requests if we have D1 configured
203
        	if (!isD1Enabled()) {
204
        		ServiceFailure se = new ServiceFailure("0000", "DataONE services are not enabled on this node");
205
                serializeException(se, response.getOutputStream());
206
                return;
207
        	}
208
209 6284 leinfelder
        	// get the resource
210
            String resource = request.getPathInfo();
211
            resource = resource.substring(resource.indexOf("/") + 1);
212 6264 leinfelder
213 6284 leinfelder
            // default to node info
214
            if (resource.equals("")) {
215 6264 leinfelder
                resource = RESOURCE_NODE;
216
            }
217 6284 leinfelder
218
            // get the rest of the path info
219
            String extra = null;
220 6264 leinfelder
221 6272 leinfelder
            logMetacat.debug("handling verb " + httpVerb + " request with resource '" + resource + "'");
222
            logMetacat.debug("resource: '" + resource + "'");
223 6264 leinfelder
            boolean status = false;
224
225
            if (resource != null) {
226
227 6284 leinfelder
                if (resource.startsWith(RESOURCE_NODE)) {
228 6264 leinfelder
                    // node response
229
                    node();
230
                    status = true;
231 8874 leinfelder
                } else if (resource.startsWith(RESOURCE_TOKEN)) {
232
                    logMetacat.debug("Using resource 'token'");
233
                    // get
234
                    if (httpVerb == GET) {
235
                    	// after the command
236
                        getToken();
237
                        status = true;
238
                    }
239
240 9173 leinfelder
                } else if (resource.startsWith(RESOURCE_WHOAMI)) {
241
                    logMetacat.debug("Using resource 'whoami'");
242
                    // get
243
                    if (httpVerb == GET) {
244
                    	// after the command
245
                        whoami();
246
                        status = true;
247
                    }
248
249 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_IS_AUTHORIZED)) {
250 6264 leinfelder
                    if (httpVerb == GET) {
251 6514 leinfelder
                    	// after the command
252
                        extra = parseTrailing(resource, RESOURCE_IS_AUTHORIZED);
253 9300 tao
                        extra = decode(extra);
254 6264 leinfelder
	                	// check the access rules
255 6284 leinfelder
	                    isAuthorized(extra);
256 6264 leinfelder
	                    status = true;
257 6272 leinfelder
	                    logMetacat.debug("done getting access");
258 6264 leinfelder
                    }
259 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_META)) {
260 6272 leinfelder
                    logMetacat.debug("Using resource 'meta'");
261 6264 leinfelder
                    // get
262
                    if (httpVerb == GET) {
263 9122 tao
                        logMetacat.debug("Using resource 'meta' for GET");
264 6514 leinfelder
                    	// after the command
265
                        extra = parseTrailing(resource, RESOURCE_META);
266 9300 tao
                        extra = decode(extra);
267 6284 leinfelder
                        getSystemMetadataObject(extra);
268 6264 leinfelder
                        status = true;
269 9122 tao
                    } else if (httpVerb == PUT) {
270
                        logMetacat.debug("Using resource 'meta' for PUT");
271
                        updateSystemMetadata();
272
                        status = true;
273 6264 leinfelder
                    }
274
275 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_OBJECTS)) {
276 6272 leinfelder
                    logMetacat.debug("Using resource 'object'");
277 6514 leinfelder
                    // after the command
278
                    extra = parseTrailing(resource, RESOURCE_OBJECTS);
279 9300 tao
                    extra = decode(extra);
280 6284 leinfelder
                    logMetacat.debug("objectId: " + extra);
281 6264 leinfelder
                    logMetacat.debug("verb:" + httpVerb);
282
283
                    if (httpVerb == GET) {
284 6284 leinfelder
                        getObject(extra);
285 6264 leinfelder
                        status = true;
286
                    } else if (httpVerb == POST) {
287 6972 leinfelder
                    	// part of the params, not the URL
288
                        putObject(null, FUNCTION_NAME_INSERT);
289 6264 leinfelder
                        status = true;
290
                    } else if (httpVerb == PUT) {
291 6284 leinfelder
                        putObject(extra, FUNCTION_NAME_UPDATE);
292 6264 leinfelder
                        status = true;
293
                    } else if (httpVerb == DELETE) {
294 6284 leinfelder
                        deleteObject(extra);
295 6264 leinfelder
                        status = true;
296
                    } else if (httpVerb == HEAD) {
297 6284 leinfelder
                        describeObject(extra);
298 6264 leinfelder
                        status = true;
299
                    }
300
301 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_LOG)) {
302 6272 leinfelder
                    logMetacat.debug("Using resource 'log'");
303 6264 leinfelder
                    // handle log events
304
                    if (httpVerb == GET) {
305
                        getLog();
306
                        status = true;
307
                    }
308 7153 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_ARCHIVE)) {
309
                    logMetacat.debug("Using resource " + Constants.RESOURCE_ARCHIVE);
310
                    // handle archive events
311
                    if (httpVerb == PUT) {
312
                        extra = parseTrailing(resource, Constants.RESOURCE_ARCHIVE);
313 9300 tao
                        extra = decode(extra);
314 7153 leinfelder
                        archive(extra);
315
                        status = true;
316
                    }
317 7019 leinfelder
                } else if (resource.startsWith(Constants.RESOURCE_CHECKSUM)) {
318 6272 leinfelder
                    logMetacat.debug("Using resource 'checksum'");
319 6264 leinfelder
                    // handle checksum requests
320
                    if (httpVerb == GET) {
321 6514 leinfelder
                    	// after the command
322 7019 leinfelder
                        extra = parseTrailing(resource, Constants.RESOURCE_CHECKSUM);
323 9300 tao
                        extra = decode(extra);
324 6284 leinfelder
                        checksum(extra);
325 6264 leinfelder
                        status = true;
326
                    }
327
                } else if (resource.startsWith(RESOURCE_MONITOR)) {
328
                    // there are various parts to monitoring
329
                    if (httpVerb == GET) {
330 6514 leinfelder
                    	// after the command
331
                        extra = parseTrailing(resource, RESOURCE_MONITOR);
332 9300 tao
                        extra = decode(extra);
333 6803 leinfelder
                        // ping
334
                        if (extra.toLowerCase().equals("ping")) {
335
                            logMetacat.debug("processing ping request");
336
                            Date result = MNodeService.getInstance(request).ping();
337
                            // TODO: send to output
338
                            status = true;
339
340
                        }
341
342 6264 leinfelder
                    }
343 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_REPLICATE)) {
344 6264 leinfelder
                	if (httpVerb == POST) {
345 6272 leinfelder
	                    logMetacat.debug("processing replicate request");
346 6264 leinfelder
	                    replicate();
347
	                    status = true;
348
                	}
349 6284 leinfelder
                } else if (resource.startsWith(RESOURCE_ERROR)) {
350 6264 leinfelder
	                // sync error
351
	                if (httpVerb == POST) {
352
	                    syncError();
353
	                    status = true;
354
	                }
355 6604 cjones
                } else if (resource.startsWith(RESOURCE_META_CHANGED)) {
356
                    // system metadata changed
357
                    if (httpVerb == POST) {
358 6650 leinfelder
                        systemMetadataChanged();
359 6604 cjones
                        status = true;
360
                    }
361
                } else if (resource.startsWith(RESOURCE_REPLICAS)) {
362
                    // get replica
363
                    if (httpVerb == GET) {
364
                        extra = parseTrailing(resource, RESOURCE_REPLICAS);
365 9300 tao
                        extra = decode(extra);
366 6604 cjones
                        getReplica(extra);
367
                        status = true;
368
                    }
369 7417 leinfelder
                } else if (resource.startsWith(RESOURCE_QUERY)) {
370
	                logMetacat.debug("Using resource " + RESOURCE_QUERY);
371
	                // after the command
372
	                extra = parseTrailing(resource, RESOURCE_QUERY);
373
	                logMetacat.debug("query extra: " + extra);
374
375
	                String engine = null;
376
	                String query = null;
377
378
	                if (extra != null) {
379
		                // get the engine
380
		                int engineIndex = extra.length();
381
		                if (extra.indexOf("/") > -1) {
382
		                	engineIndex = extra.indexOf("/");
383
		                }
384
		                engine = extra.substring(0, engineIndex);
385 9300 tao
		                engine = decode(engine);
386 7417 leinfelder
		                logMetacat.debug("query engine: " + engine);
387
388 9333 leinfelder
		                // check the query string first
389
		                query = request.getQueryString();
390
391
		                // if null, look at the whole endpoint
392
		                if (query == null) {
393
			                // get the query if it is there
394
			                query = extra.substring(engineIndex, extra.length());
395
			                if (query != null && query.length() == 0) {
396
			                	query = null;
397
			                } else {
398
			                	if (query.startsWith("/")) {
399
			                		query = query.substring(1);
400
			                    }
401
			                }
402 7417 leinfelder
		                }
403 9333 leinfelder
404 9300 tao
		                query = decode(query);
405 7417 leinfelder
		                logMetacat.debug("query: " + query);
406
407
	                }
408
	                logMetacat.debug("verb:" + httpVerb);
409
	                if (httpVerb == GET) {
410
	                    doQuery(engine, query);
411
	                    status = true;
412
	                }
413 7441 leinfelder
                } else if (resource.startsWith(RESOURCE_GENERATE_ID)) {
414
                	// generate an id
415
                    if (httpVerb == POST) {
416
                        generateIdentifier();
417
                        status = true;
418
                    }
419 7864 leinfelder
                } else if (resource.startsWith(RESOURCE_PUBLISH)) {
420
                    logMetacat.debug("Using resource: " + RESOURCE_PUBLISH);
421
                    // PUT
422
                    if (httpVerb == PUT) {
423
                    	// after the command
424
                        extra = parseTrailing(resource, RESOURCE_PUBLISH);
425 9300 tao
                        extra = decode(extra);
426 7864 leinfelder
                        publish(extra);
427
                        status = true;
428
                    }
429 7855 leinfelder
                } else if (resource.startsWith(RESOURCE_PACKAGE)) {
430
                    logMetacat.debug("Using resource: " + RESOURCE_PACKAGE);
431 8810 leinfelder
                    // after the command
432
                    extra = parseTrailing(resource, RESOURCE_PACKAGE);
433
434
                    String format = null;
435
	                String pid = null;
436
437
	                if (extra != null) {
438
		                // get the format
439
		                int formatIndex = extra.length();
440
		                if (extra.indexOf("/") > -1) {
441
		                	formatIndex = extra.indexOf("/");
442
		                }
443
		                format = extra.substring(0, formatIndex);
444 9300 tao
		                format = decode(format);
445 8810 leinfelder
		                logMetacat.debug("package format: " + format);
446
447
		                // get the pid if it is there
448
		                pid = extra.substring(formatIndex, extra.length());
449
		                if (pid != null && pid.length() == 0) {
450
		                	pid = null;
451
		                } else {
452
		                	if (pid.startsWith("/")) {
453
		                		pid = pid.substring(1);
454
		                    }
455
		                }
456 9300 tao
		                pid = decode(pid);
457 8810 leinfelder
		                logMetacat.debug("pid: " + pid);
458
459
	                }
460
461 7855 leinfelder
                    // get
462
                    if (httpVerb == GET) {
463 8810 leinfelder
464
                        getPackage(format, pid);
465 7855 leinfelder
                        status = true;
466 7861 leinfelder
                    }
467
                } else if (resource.startsWith(RESOURCE_VIEWS)) {
468
	                logMetacat.debug("Using resource " + RESOURCE_VIEWS);
469
	                // after the command
470
	                extra = parseTrailing(resource, RESOURCE_VIEWS);
471
	                logMetacat.debug("view extra: " + extra);
472
473
	                String format = null;
474
	                String pid = null;
475
476
	                if (extra != null) {
477
		                // get the format
478
		                int formatIndex = extra.length();
479
		                if (extra.indexOf("/") > -1) {
480
		                	formatIndex = extra.indexOf("/");
481
		                }
482
		                format = extra.substring(0, formatIndex);
483 9300 tao
		                format = decode(format);
484 7861 leinfelder
		                logMetacat.debug("view format: " + format);
485
486
		                // get the pid if it is there
487
		                pid = extra.substring(formatIndex, extra.length());
488
		                if (pid != null && pid.length() == 0) {
489
		                	pid = null;
490
		                } else {
491
		                	if (pid.startsWith("/")) {
492
		                		pid = pid.substring(1);
493
		                    }
494
		                }
495 9300 tao
		                pid = decode(pid);
496 7861 leinfelder
		                logMetacat.debug("pid: " + pid);
497
498
	                }
499
	                logMetacat.debug("verb:" + httpVerb);
500
	                if (httpVerb == GET) {
501
	                    doViews(format, pid);
502
	                    status = true;
503
	                }
504 9301 tao
                } else {
505
                    throw new InvalidRequest("0000", "No resource matched for " + resource);
506
                }
507 6264 leinfelder
508
                if (!status) {
509 6273 leinfelder
                	throw new ServiceFailure("0000", "Unknown error, status = " + status);
510 6264 leinfelder
                }
511
            } else {
512 6273 leinfelder
            	throw new InvalidRequest("0000", "No resource matched for " + resource);
513 6264 leinfelder
            }
514
        } catch (BaseException be) {
515
        	// report Exceptions as clearly as possible
516
        	OutputStream out = null;
517
			try {
518
				out = response.getOutputStream();
519
			} catch (IOException e) {
520
				logMetacat.error("Could not get output stream from response", e);
521
			}
522
            serializeException(be, out);
523
        } catch (Exception e) {
524 6273 leinfelder
            // report Exceptions as clearly and generically as possible
525
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
526
        	OutputStream out = null;
527
			try {
528
				out = response.getOutputStream();
529
			} catch (IOException ioe) {
530
				logMetacat.error("Could not get output stream from response", ioe);
531
			}
532
			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
533
            serializeException(se, out);
534 6264 leinfelder
        }
535
    }
536
537 6604 cjones
538 7417 leinfelder
    private void doQuery(String engine, String query) {
539
540
		OutputStream out = null;
541
542
    	try {
543
    		// NOTE: we set the session explicitly for the MNode instance since these methods do not provide a parameter
544
	    	if (engine == null) {
545
	    		// just looking for list of engines
546
	    		MNodeService mnode = MNodeService.getInstance(request);
547
    			mnode.setSession(session);
548 8810 leinfelder
	    		QueryEngineList qel = mnode.listQueryEngines(session);
549 7417 leinfelder
	    		response.setContentType("text/xml");
550
	            response.setStatus(200);
551
	            out = response.getOutputStream();
552
	            TypeMarshaller.marshalTypeToOutputStream(qel, out);
553
	            return;
554
	    	} else {
555
	    		if (query != null) {
556
	    			MNodeService mnode = MNodeService.getInstance(request);
557
	    			mnode.setSession(session);
558 8810 leinfelder
	    			InputStream stream = mnode.query(session, engine, query);
559 7417 leinfelder
560 7757 leinfelder
	    			// set the content-type if we have it from the implementation
561
	    			if (stream instanceof ContentTypeInputStream) {
562
		    			//response.setContentType("application/octet-stream");
563
		    			//response.setContentType("text/xml");
564
	    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
565
	    			}
566 7417 leinfelder
	                response.setStatus(200);
567
	                out = response.getOutputStream();
568
	                // write the results to the output stream
569
	                IOUtils.copyLarge(stream, out);
570
	                return;
571
	    		} else {
572
	    			MNodeService mnode = MNodeService.getInstance(request);
573
	    			mnode.setSession(session);
574 8810 leinfelder
	    			QueryEngineDescription qed = mnode.getQueryEngineDescription(session, engine);
575 7417 leinfelder
	    			response.setContentType("text/xml");
576
		            response.setStatus(200);
577
		            out = response.getOutputStream();
578
		            TypeMarshaller.marshalTypeToOutputStream(qed, out);
579
		            return;
580
	    		}
581
	    	}
582
583
584
    	} catch (BaseException be) {
585
        	// report Exceptions as clearly as possible
586
			try {
587
				out = response.getOutputStream();
588
			} catch (IOException e) {
589
				logMetacat.error("Could not get output stream from response", e);
590
			}
591
            serializeException(be, out);
592
        } catch (Exception e) {
593
            // report Exceptions as clearly and generically as possible
594
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
595
			try {
596
				out = response.getOutputStream();
597
			} catch (IOException ioe) {
598
				logMetacat.error("Could not get output stream from response", ioe);
599
			}
600
			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
601
            serializeException(se, out);
602
        }
603
    }
604
605 7861 leinfelder
    private void doViews(String format, String pid) {
606
607
		OutputStream out = null;
608
		MNodeService mnode = MNodeService.getInstance(request);
609
610
    	try {
611
    		// get a list of views
612
    		if (pid != null) {
613
    			Identifier identifier = new Identifier();
614
    			identifier.setValue(pid);
615 8810 leinfelder
				InputStream stream = mnode.view(session, format, identifier);
616 7861 leinfelder
617
    			// set the content-type if we have it from the implementation
618
    			if (stream instanceof ContentTypeInputStream) {
619
    				response.setContentType(((ContentTypeInputStream) stream).getContentType());
620
    			}
621
                response.setStatus(200);
622
                out = response.getOutputStream();
623
                // write the results to the output stream
624
                IOUtils.copyLarge(stream, out);
625
                return;
626
    		} else {
627
    			// TODO: list the registered views
628 9148 tao
                //BaseException ni = new NotImplemented("9999", "MN.listViews() is not implemented at this node");
629
				//throw ni;
630
    		    OptionList list = mnode.listViews(session);
631
632
    	        response.setContentType("text/xml");
633
    	        response.setStatus(200);
634
    	        TypeMarshaller.marshalTypeToOutputStream(list, response.getOutputStream());
635 7861 leinfelder
    		}
636
637
638
    	} catch (BaseException be) {
639
        	// report Exceptions as clearly as possible
640
			try {
641
				out = response.getOutputStream();
642
			} catch (IOException e) {
643
				logMetacat.error("Could not get output stream from response", e);
644
			}
645
            serializeException(be, out);
646
        } catch (Exception e) {
647
            // report Exceptions as clearly and generically as possible
648
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
649
			try {
650
				out = response.getOutputStream();
651
			} catch (IOException ioe) {
652
				logMetacat.error("Could not get output stream from response", ioe);
653
			}
654
			ServiceFailure se = new ServiceFailure("0000", e.getMessage());
655
            serializeException(se, out);
656
        }
657
    }
658 7417 leinfelder
659 6273 leinfelder
    /**
660 6604 cjones
     * Handles notification of system metadata changes for the given identifier
661
     *
662
     * @param id  the identifier for the object
663
     * @throws InvalidToken
664
     * @throws InvalidRequest
665
     * @throws NotAuthorized
666
     * @throws ServiceFailure
667
     * @throws NotImplemented
668
     */
669 6650 leinfelder
    private void systemMetadataChanged()
670 6604 cjones
        throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest,
671
        InvalidToken {
672
673 9327 tao
        //final long serialVersion = 0L;
674 6604 cjones
        String serialVersionStr = null;
675
        String dateSysMetaLastModifiedStr = null;
676
677 6660 leinfelder
        // mkae sure we have the multipart params
678
        try {
679
			initMultipartParams();
680
		} catch (Exception e1) {
681
			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
682
		}
683
684 6650 leinfelder
        // get the pid
685 9327 tao
        String id = null;
686 6650 leinfelder
        try {
687 9327 tao
        	id = multipartparams.get("pid").get(0);
688 6650 leinfelder
        } catch (NullPointerException e) {
689
            String msg = "The 'pid' must be provided as a parameter and was not.";
690
            logMetacat.error(msg);
691
            throw new InvalidRequest("1334", msg);
692 9327 tao
        }
693
        final Identifier pid = new Identifier();
694
        pid.setValue(id);
695 6650 leinfelder
696 6604 cjones
        // get the serialVersion
697
        try {
698 6660 leinfelder
            serialVersionStr = multipartparams.get("serialVersion").get(0);
699 6604 cjones
        } catch (NullPointerException e) {
700
            String msg = "The 'serialVersion' must be provided as a parameter and was not.";
701
            logMetacat.error(msg);
702
            throw new InvalidRequest("1334", msg);
703
704 9327 tao
        }
705 6604 cjones
706 9327 tao
        final long serialVersion = (new Long(serialVersionStr)).longValue();
707
708 6604 cjones
        // get the dateSysMetaLastModified
709
        try {
710 6660 leinfelder
            dateSysMetaLastModifiedStr = multipartparams.get("dateSysMetaLastModified").get(0);
711 6604 cjones
712 9327 tao
713 6604 cjones
        } catch (NullPointerException e) {
714
            String msg =
715
                "The 'dateSysMetaLastModified' must be provided as a " +
716
                "parameter and was not, or was an invalid representation of the timestamp.";
717
            logMetacat.error(msg);
718
            throw new InvalidRequest("1334", msg);
719
720 9327 tao
        }
721
        final Date dateSysMetaLastModified = DateTimeMarshaller.deserializeDateToUTC(dateSysMetaLastModifiedStr);
722 6604 cjones
723 9327 tao
        // run it in a thread to avoid connection timeout
724
        Runnable runner = new Runnable() {
725
            @Override
726
            public void run() {
727
                try {
728
                   // call the service
729
                    MNodeService.getInstance(request).systemMetadataChanged(session, pid, serialVersion, dateSysMetaLastModified);
730
                } catch (Exception e) {
731
                    logMetacat.error("Error running replication: " + e.getMessage(), e);
732
                    throw new RuntimeException(e.getMessage(), e);
733
                }
734
            }
735
        };
736
        // submit the task, and that's it
737
        executor.submit(runner);
738
739
        // thread was started, so we return success
740 6604 cjones
        response.setStatus(200);
741
    }
742 7441 leinfelder
743
    /**
744
     * Handles identifier generation calls
745
     *
746
     * @throws InvalidRequest
747
     * @throws NotImplemented
748
     * @throws NotAuthorized
749
     * @throws ServiceFailure
750
     * @throws InvalidToken
751
     * @throws IOException
752
     * @throws JiBXException
753
     */
754
    private void generateIdentifier() throws InvalidToken, ServiceFailure, NotAuthorized, NotImplemented, InvalidRequest, IOException, JiBXException {
755
756
        // make sure we have the multipart params
757
        try {
758
			initMultipartParams();
759
		} catch (Exception e1) {
760
			throw new ServiceFailure("1333", "Could not collect the multipart params for the request");
761
		}
762
763
        // get the scheme
764
		String scheme = null;
765
        try {
766
        	scheme = multipartparams.get("scheme").get(0);
767
        } catch (NullPointerException e) {
768
            String msg = "The 'scheme' parameter was not provided, using default";
769
            logMetacat.warn(msg);
770
        }
771
772
        // get the fragment
773
		String fragment = null;
774
        try {
775
        	fragment = multipartparams.get("fragment").get(0);
776
        } catch (NullPointerException e) {
777
            String msg = "The 'fragment' parameter was not provided, using default";
778
            logMetacat.warn(msg);
779
        }
780 6604 cjones
781 7441 leinfelder
        // call the service
782
        Identifier identifier = MNodeService.getInstance(request).generateIdentifier(session, scheme, fragment);
783
        response.setStatus(200);
784
        response.setContentType("text/xml");
785
        OutputStream out = response.getOutputStream();
786
        TypeMarshaller.marshalTypeToOutputStream(identifier, out);
787
    }
788
789 6604 cjones
    /**
790 6273 leinfelder
     * Checks the access policy
791
     * @param id
792
     * @return
793
     * @throws ServiceFailure
794
     * @throws InvalidToken
795
     * @throws NotFound
796
     * @throws NotAuthorized
797
     * @throws NotImplemented
798
     * @throws InvalidRequest
799
     */
800 6264 leinfelder
    private boolean isAuthorized(String id) throws ServiceFailure, InvalidToken, NotFound, NotAuthorized, NotImplemented, InvalidRequest {
801
		Identifier pid = new Identifier();
802
		pid.setValue(id);
803
		Permission permission = null;
804
		try {
805 6509 leinfelder
			String perm = params.get("action")[0];
806 6373 leinfelder
			permission = Permission.convert(perm);
807 6264 leinfelder
		} catch (Exception e) {
808
			logMetacat.warn("No permission specified");
809
		}
810 6542 leinfelder
		boolean result = MNodeService.getInstance(request).isAuthorized(session, pid, permission);
811 6264 leinfelder
		response.setStatus(200);
812
		response.setContentType("text/xml");
813
		return result;
814
    }
815
816 8874 leinfelder
    private void getToken() throws Exception {
817
818
		if (this.session != null) {
819
			String userId = this.session.getSubject().getValue();
820 9009 leinfelder
			String fullName = null;
821
			try {
822
				Person person = this.session.getSubjectInfo().getPerson(0);
823
				fullName = person.getGivenName(0) + " " + person.getFamilyName();
824
			} catch (Exception e) {
825
				logMetacat.warn(e.getMessage(), e);
826
			}
827
828 8874 leinfelder
			String token = null;
829 9164 leinfelder
			token = TokenGenerator.getInstance().getJWT(userId, fullName);
830 8874 leinfelder
831
			response.setStatus(200);
832
			response.setContentType("text/plain");
833
	        OutputStream out = response.getOutputStream();
834
	        out.write(token.getBytes(MetaCatServlet.DEFAULT_ENCODING));
835
	        out.close();
836
		} else {
837
			response.setStatus(401);
838
			response.setContentType("text/plain");
839
			OutputStream out = response.getOutputStream();
840
	        out.write("No session information found".getBytes(MetaCatServlet.DEFAULT_ENCODING));
841
	        out.close();
842
		}
843
844
    }
845
846 9173 leinfelder
    private void whoami() throws Exception {
847
848
		if (this.session != null) {
849
			Subject subject = this.session.getSubject();
850
			SubjectInfo subjectInfo = null;
851
			try {
852
				subjectInfo = this.session.getSubjectInfo();
853
			} catch (Exception e) {
854
				logMetacat.warn(e.getMessage(), e);
855
			}
856
857
			response.setStatus(200);
858
			response.setContentType("text/plain");
859
	        OutputStream out = response.getOutputStream();
860
861
	        if (subjectInfo != null) {
862
		        TypeMarshaller.marshalTypeToOutputStream(subjectInfo, out);
863
	        } else {
864
		        TypeMarshaller.marshalTypeToOutputStream(subject, out);
865
	        }
866
867
	        out.close();
868
		} else {
869
			response.setStatus(401);
870
			response.setContentType("text/plain");
871
			OutputStream out = response.getOutputStream();
872
	        out.write("No session information found".getBytes(MetaCatServlet.DEFAULT_ENCODING));
873
	        out.close();
874
		}
875
876
    }
877
878 6273 leinfelder
    /**
879
     * Processes failed synchronization message
880
     * @throws NotImplemented
881
     * @throws ServiceFailure
882
     * @throws NotAuthorized
883
     * @throws InvalidRequest
884
     * @throws JiBXException
885 6367 leinfelder
     * @throws IllegalAccessException
886
     * @throws InstantiationException
887
     * @throws IOException
888 6273 leinfelder
     */
889 6367 leinfelder
    private void syncError() throws NotImplemented, ServiceFailure, NotAuthorized, InvalidRequest, JiBXException, IOException, InstantiationException, IllegalAccessException {
890 6264 leinfelder
    	SynchronizationFailed syncFailed = null;
891 6472 leinfelder
		try {
892
			syncFailed = collectSynchronizationFailed();
893
		} catch (ParserConfigurationException e) {
894
			throw new ServiceFailure("2161", e.getMessage());
895
		} catch (SAXException e) {
896
			throw new ServiceFailure("2161", e.getMessage());
897
		}
898
899 6542 leinfelder
		MNodeService.getInstance(request).synchronizationFailed(session, syncFailed);
900 6264 leinfelder
    }
901 6472 leinfelder
902 8810 leinfelder
	/**
903 6273 leinfelder
     * Calculate the checksum
904
     * @throws NotImplemented
905
     * @throws JiBXException
906
     * @throws IOException
907
     * @throws InvalidToken
908
     * @throws ServiceFailure
909
     * @throws NotAuthorized
910
     * @throws NotFound
911
     * @throws InvalidRequest
912
     */
913 6285 cjones
    private void checksum(String pid) throws NotImplemented, JiBXException, IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest {
914 6264 leinfelder
    	String checksumAlgorithm = "MD5";
915 7222 leinfelder
    	try {
916
    		checksumAlgorithm = PropertyService.getProperty("dataone.checksumAlgorithm.default");
917
        } catch(Exception e) {
918
        	logMetacat.warn("Could not lookup configured default checksum algorithm, using: " + checksumAlgorithm);
919
        }
920 6284 leinfelder
921 6285 cjones
        Identifier pidid = new Identifier();
922
        pidid.setValue(pid);
923 6264 leinfelder
        try {
924
            checksumAlgorithm = params.get("checksumAlgorithm")[0];
925
        } catch(Exception e) {
926 7222 leinfelder
            //do nothing.  use the default
927 6264 leinfelder
        	logMetacat.warn("No algorithm specified, using default: " + checksumAlgorithm);
928
        }
929 6285 cjones
        logMetacat.debug("getting checksum for object " + pid + " with algorithm " + checksumAlgorithm);
930 6273 leinfelder
931 6542 leinfelder
        Checksum c = MNodeService.getInstance(request).getChecksum(session, pidid, checksumAlgorithm);
932 6273 leinfelder
        logMetacat.debug("got checksum " + c.getValue());
933
        response.setStatus(200);
934
        logMetacat.debug("serializing response");
935 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(c, response.getOutputStream());
936 6273 leinfelder
        logMetacat.debug("done serializing response.");
937
938 6264 leinfelder
    }
939
940
	/**
941
     * handle the replicate action for MN
942 6273 leinfelder
	 * @throws JiBXException
943
	 * @throws FileUploadException
944
	 * @throws IOException
945
	 * @throws InvalidRequest
946
	 * @throws ServiceFailure
947
	 * @throws UnsupportedType
948
	 * @throws InsufficientResources
949
	 * @throws NotAuthorized
950
	 * @throws NotImplemented
951 6367 leinfelder
	 * @throws IllegalAccessException
952
	 * @throws InstantiationException
953 7142 leinfelder
	 * @throws InvalidToken
954 6264 leinfelder
     */
955 6678 cjones
    private void replicate()
956
        throws ServiceFailure, InvalidRequest, IOException, FileUploadException,
957
        JiBXException, NotImplemented, NotAuthorized, InsufficientResources,
958 7142 leinfelder
        UnsupportedType, InstantiationException, IllegalAccessException, InvalidToken {
959 6264 leinfelder
960 6272 leinfelder
        logMetacat.debug("in POST replicate()");
961 6264 leinfelder
962 7064 leinfelder
        // somewhat unorthodox, but the call is asynchronous and we'd like to return this info sooner
963 7142 leinfelder
        boolean allowed = false;
964 7064 leinfelder
        if (session == null) {
965
        	String msg = "No session was provided.";
966
            NotAuthorized failure = new NotAuthorized("2152", msg);
967
        	throw failure;
968 7142 leinfelder
        } else {
969
        	allowed = MNodeService.getInstance(request).isAdminAuthorized(session);
970
        	if (!allowed) {
971
        		String msg = "User is not an admin user";
972
                NotAuthorized failure = new NotAuthorized("2152", msg);
973
            	throw failure;
974
        	}
975 7064 leinfelder
        }
976
977 8810 leinfelder
        // parse the systemMetadata
978
        Map<String, File> files = collectMultipartFiles();
979
        final SystemMetadata sysmeta = TypeMarshaller.unmarshalTypeFromFile(SystemMetadata.class, files.get("sysmeta"));
980 6264 leinfelder
981 6273 leinfelder
        String sn = multipartparams.get("sourceNode").get(0);
982 6272 leinfelder
        logMetacat.debug("sourceNode: " + sn);
983 6679 leinfelder
        final NodeReference sourceNode = new NodeReference();
984 6548 cjones
        sourceNode.setValue(sn);
985 6679 leinfelder
986
        // run it in a thread to avoid connection timeout
987
        Runnable runner = new Runnable() {
988
			@Override
989
			public void run() {
990
				try {
991
			        MNodeService.getInstance(request).replicate(session, sysmeta, sourceNode);
992
				} catch (Exception e) {
993 7091 leinfelder
					logMetacat.error("Error running replication: " + e.getMessage(), e);
994 6679 leinfelder
					throw new RuntimeException(e.getMessage(), e);
995
				}
996
			}
997
    	};
998 7143 leinfelder
    	// submit the task, and that's it
999
    	executor.submit(runner);
1000 6679 leinfelder
1001
    	// thread was started, so we return success
1002 6678 cjones
        response.setStatus(200);
1003 6679 leinfelder
1004 6264 leinfelder
    }
1005 6604 cjones
1006 6264 leinfelder
    /**
1007 6604 cjones
     * Handle the getReplica action for the MN
1008
     * @param id  the identifier for the object
1009
     * @throws NotFound
1010
     * @throws ServiceFailure
1011
     * @throws NotImplemented
1012
     * @throws NotAuthorized
1013
     * @throws InvalidToken
1014
     * @throws InvalidRequest
1015
     */
1016
    private void getReplica(String id)
1017
        throws InvalidRequest, InvalidToken, NotAuthorized, NotImplemented,
1018
        ServiceFailure, NotFound {
1019
1020
        Identifier pid = new Identifier();
1021
        pid.setValue(id);
1022
        OutputStream out = null;
1023
        InputStream dataBytes = null;
1024
1025
        try {
1026
            // call the service
1027
            dataBytes = MNodeService.getInstance(request).getReplica(session, pid);
1028
1029
            response.setContentType("application/octet-stream");
1030
            response.setStatus(200);
1031
            out = response.getOutputStream();
1032
            // write the object to the output stream
1033
            IOUtils.copyLarge(dataBytes, out);
1034
1035
        } catch (IOException e) {
1036
            String msg = "There was an error writing the output: " + e.getMessage();
1037
            logMetacat.error(msg);
1038
            throw new ServiceFailure("2181", msg);
1039
1040
        }
1041
1042
    }
1043
1044
    /**
1045 6264 leinfelder
     * Get the Node information
1046
     *
1047
     * @throws JiBXException
1048
     * @throws IOException
1049
     * @throws InvalidRequest
1050
     * @throws ServiceFailure
1051
     * @throws NotAuthorized
1052
     * @throws NotImplemented
1053
     */
1054
    private void node()
1055
        throws JiBXException, IOException, NotImplemented, NotAuthorized, ServiceFailure, InvalidRequest {
1056
1057 6542 leinfelder
        Node n = MNodeService.getInstance(request).getCapabilities();
1058 6264 leinfelder
1059
        response.setContentType("text/xml");
1060
        response.setStatus(200);
1061 6501 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(n, response.getOutputStream());
1062 6264 leinfelder
1063
    }
1064
1065
    /**
1066
     * MN_crud.describe()
1067
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
1068 6285 cjones
     * @param pid
1069 6273 leinfelder
     * @throws InvalidRequest
1070
     * @throws NotImplemented
1071
     * @throws NotFound
1072
     * @throws NotAuthorized
1073
     * @throws ServiceFailure
1074
     * @throws InvalidToken
1075 6264 leinfelder
     */
1076 6285 cjones
    private void describeObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest
1077 6264 leinfelder
    {
1078 7043 leinfelder
1079 6264 leinfelder
        response.setContentType("text/xml");
1080 7043 leinfelder
1081 6264 leinfelder
        Identifier id = new Identifier();
1082 6285 cjones
        id.setValue(pid);
1083 6273 leinfelder
1084 7043 leinfelder
        DescribeResponse dr = null;
1085
        try {
1086
        	dr = MNodeService.getInstance(request).describe(session, id);
1087
        } catch (BaseException e) {
1088
        	response.setStatus(e.getCode());
1089
        	response.addHeader("DataONE-Exception-Name", e.getClass().getName());
1090
            response.addHeader("DataONE-Exception-DetailCode", e.getDetail_code());
1091
            response.addHeader("DataONE-Exception-Description", e.getDescription());
1092
            response.addHeader("DataONE-Exception-PID", id.getValue());
1093
            return;
1094
		}
1095
1096
        response.setStatus(200);
1097
1098 6502 leinfelder
        //response.addHeader("pid", pid);
1099 6507 leinfelder
        response.addHeader("DataONE-Checksum", dr.getDataONE_Checksum().getAlgorithm() + "," + dr.getDataONE_Checksum().getValue());
1100 6502 leinfelder
        response.addHeader("Content-Length", dr.getContent_Length() + "");
1101
        response.addHeader("Last-Modified", DateTimeMarshaller.serializeDateToUTC(dr.getLast_Modified()));
1102 6691 leinfelder
        response.addHeader("DataONE-ObjectFormat", dr.getDataONE_ObjectFormatIdentifier().getValue());
1103 6773 leinfelder
        response.addHeader("DataONE-SerialVersion", dr.getSerialVersion().toString());
1104
1105 6502 leinfelder
1106 6264 leinfelder
    }
1107
1108
    /**
1109
     * get the logs based on passed params.  Available
1110
     * See http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
1111
     * for more info
1112 6273 leinfelder
     * @throws NotImplemented
1113
     * @throws InvalidRequest
1114
     * @throws NotAuthorized
1115
     * @throws ServiceFailure
1116
     * @throws InvalidToken
1117
     * @throws IOException
1118
     * @throws JiBXException
1119 6264 leinfelder
     */
1120 6273 leinfelder
    private void getLog() throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest, NotImplemented, IOException, JiBXException
1121 6264 leinfelder
    {
1122 6273 leinfelder
1123
        Date fromDate = null;
1124
        Date toDate = null;
1125 8810 leinfelder
        String event = null;
1126 6273 leinfelder
        Integer start = null;
1127
        Integer count = null;
1128 7099 leinfelder
        String pidFilter = null;
1129 6273 leinfelder
1130 6264 leinfelder
        try {
1131 6273 leinfelder
        	String fromDateS = params.get("fromDate")[0];
1132
            logMetacat.debug("param fromDateS: " + fromDateS);
1133 6469 leinfelder
            fromDate = DateTimeMarshaller.deserializeDateToUTC(fromDateS);
1134 6273 leinfelder
        } catch (Exception e) {
1135
        	logMetacat.warn("Could not parse fromDate: " + e.getMessage());
1136 6264 leinfelder
        }
1137 6273 leinfelder
        try {
1138
        	String toDateS = params.get("toDate")[0];
1139
            logMetacat.debug("param toDateS: " + toDateS);
1140 6469 leinfelder
            toDate = DateTimeMarshaller.deserializeDateToUTC(toDateS);
1141 6273 leinfelder
        } catch (Exception e) {
1142
        	logMetacat.warn("Could not parse toDate: " + e.getMessage());
1143
		}
1144
        try {
1145 8810 leinfelder
        	event = params.get("event")[0];
1146 6273 leinfelder
        } catch (Exception e) {
1147
        	logMetacat.warn("Could not parse event: " + e.getMessage());
1148
		}
1149
        logMetacat.debug("fromDate: " + fromDate + " toDate: " + toDate);
1150
1151
        try {
1152
        	start =  Integer.parseInt(params.get("start")[0]);
1153
        } catch (Exception e) {
1154
			logMetacat.warn("Could not parse start: " + e.getMessage());
1155
		}
1156
        try {
1157
        	count =  Integer.parseInt(params.get("count")[0]);
1158
        } catch (Exception e) {
1159
			logMetacat.warn("Could not parse count: " + e.getMessage());
1160
		}
1161
1162 7099 leinfelder
        try {
1163
            pidFilter = params.get("pidFilter")[0];
1164
        } catch (Exception e) {
1165
            logMetacat.warn("Could not parse pidFilter: " + e.getMessage());
1166
        }
1167
1168 6273 leinfelder
        logMetacat.debug("calling getLogRecords");
1169 7101 leinfelder
        Log log = MNodeService.getInstance(request).getLogRecords(session, fromDate, toDate, event, pidFilter, start, count);
1170 6273 leinfelder
1171
        OutputStream out = response.getOutputStream();
1172
        response.setStatus(200);
1173
        response.setContentType("text/xml");
1174
1175 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(log, out);
1176 6273 leinfelder
1177 6264 leinfelder
    }
1178
1179 7417 leinfelder
1180
1181 6264 leinfelder
    /**
1182
     * Implements REST version of DataONE CRUD API --> get
1183 6285 cjones
     * @param pid ID of data object to be read
1184 6273 leinfelder
     * @throws NotImplemented
1185
     * @throws InvalidRequest
1186
     * @throws NotFound
1187
     * @throws NotAuthorized
1188
     * @throws ServiceFailure
1189
     * @throws InvalidToken
1190
     * @throws IOException
1191
     * @throws JiBXException
1192 6264 leinfelder
     */
1193 6285 cjones
    protected void getObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
1194 6264 leinfelder
        OutputStream out = null;
1195 6273 leinfelder
1196 6285 cjones
        if (pid != null) { //get a specific document
1197 6273 leinfelder
            Identifier id = new Identifier();
1198 6285 cjones
            id.setValue(pid);
1199 6273 leinfelder
1200 6542 leinfelder
            SystemMetadata sm = MNodeService.getInstance(request).getSystemMetadata(session, id);
1201 6264 leinfelder
1202 7412 leinfelder
            // set the headers for the content
1203 9235 leinfelder
            String mimeType = null;
1204
            String charset = null;
1205 9244 leinfelder
            ObjectFormat objectFormat = null;
1206 9235 leinfelder
1207 9244 leinfelder
            try {
1208
            	objectFormat = ObjectFormatCache.getInstance().getFormat(sm.getFormatId());
1209
        	} catch (BaseException be) {
1210
        		logMetacat.warn("Could not lookup ObjectFormat for: " + sm.getFormatId(), be);
1211
        	}
1212 9235 leinfelder
            // do we have mediaType/encoding in SM?
1213
            MediaType mediaType = sm.getMediaType();
1214
            if (mediaType == null) {
1215
            	try {
1216 9244 leinfelder
            		mediaType = objectFormat.getMediaType();
1217
            	} catch (Exception e) {
1218
            		logMetacat.warn("Could not lookup MediaType for: " + sm.getFormatId(), e);
1219 9235 leinfelder
            	}
1220
            }
1221
            if (mediaType != null) {
1222 9268 tao
                mimeType = mediaType.getName();
1223
                if (mediaType.getPropertyList() != null) {
1224
                	Iterator<MediaTypeProperty> iter = mediaType.getPropertyList().iterator();
1225 9235 leinfelder
                	while (iter.hasNext()) {
1226
                		MediaTypeProperty mtp = iter.next();
1227
                		if (mtp.getName().equalsIgnoreCase("charset")) {
1228
                			charset = mtp.getValue();
1229
                			mimeType += "; charset=" + charset;
1230
                			break;
1231
                		}
1232
                	}
1233
                }
1234
            }
1235
            // check object format
1236
1237
            // use the fallback from v1 impl
1238 7412 leinfelder
            if (mimeType == null) {
1239 9235 leinfelder
	            mimeType = ObjectFormatInfo.instance().getMimeType(sm.getFormatId().getValue());
1240
1241
	            // still null?
1242
	            if (mimeType == null) {
1243
	            	mimeType = "application/octet-stream";
1244
	            }
1245 6273 leinfelder
            }
1246 9235 leinfelder
1247
            // check for filename in SM first
1248
            String filename = sm.getFileName();
1249
            // then fallback to using id and extension
1250
            if (filename == null) {
1251 9244 leinfelder
	            String extension = objectFormat.getExtension();
1252
	            if (extension == null) {
1253
	            	extension = ObjectFormatInfo.instance().getExtension(sm.getFormatId().getValue());
1254
	            }
1255 9235 leinfelder
	            filename = id.getValue();
1256
	            if (extension != null) {
1257
	            	filename = id.getValue() + extension;
1258
	            }
1259 7412 leinfelder
            }
1260
            response.setContentType(mimeType);
1261
            response.setHeader("Content-Disposition", "inline; filename=" + filename);
1262 6273 leinfelder
1263 6542 leinfelder
            InputStream data = MNodeService.getInstance(request).get(session, id);
1264 6273 leinfelder
1265
            out = response.getOutputStream();
1266
            IOUtils.copyLarge(data, out);
1267
1268
        }
1269
        else
1270
        { //call listObjects with specified params
1271
            Date startTime = null;
1272
            Date endTime = null;
1273 7100 leinfelder
            ObjectFormatIdentifier formatId = null;
1274 8810 leinfelder
            Identifier identifier = null;
1275 7462 leinfelder
            boolean replicaStatus = true;
1276 6273 leinfelder
            int start = 0;
1277
            //TODO: make the max count into a const
1278
            int count = 1000;
1279
            Enumeration paramlist = request.getParameterNames();
1280
            while (paramlist.hasMoreElements())
1281
            { //parse the params and make the crud call
1282
                String name = (String) paramlist.nextElement();
1283
                String[] value = (String[])request.getParameterValues(name);
1284
1285 6799 cjones
                if (name.equals("fromDate") && value != null)
1286 6264 leinfelder
                {
1287 6273 leinfelder
                    try
1288 6264 leinfelder
                    {
1289 6273 leinfelder
                      //startTime = dateFormat.parse(value[0]);
1290 6469 leinfelder
                    	startTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
1291
                        //startTime = parseDateAndConvertToGMT(value[0]);
1292 6264 leinfelder
                    }
1293 6273 leinfelder
                    catch(Exception e)
1294 6799 cjones
                    {  //if we can't parse it, just don't use the fromDate param
1295
                        logMetacat.warn("Could not parse fromDate: " + value[0]);
1296 6273 leinfelder
                        startTime = null;
1297 6264 leinfelder
                    }
1298 6273 leinfelder
                }
1299 6799 cjones
                else if(name.equals("toDate") && value != null)
1300 6273 leinfelder
                {
1301
                    try
1302 6264 leinfelder
                    {
1303 6469 leinfelder
                    	endTime = DateTimeMarshaller.deserializeDateToUTC(value[0]);
1304 6264 leinfelder
                    }
1305 6273 leinfelder
                    catch(Exception e)
1306 6799 cjones
                    {  //if we can't parse it, just don't use the toDate param
1307
                        logMetacat.warn("Could not parse toDate: " + value[0]);
1308 6273 leinfelder
                        endTime = null;
1309
                    }
1310 6264 leinfelder
                }
1311 7100 leinfelder
                else if(name.equals("formatId") && value != null)
1312 6264 leinfelder
                {
1313 7100 leinfelder
                	formatId = new ObjectFormatIdentifier();
1314
                	formatId.setValue(value[0]);
1315 6264 leinfelder
                }
1316 8810 leinfelder
                else if(name.equals("identifier") && value != null)
1317
                {
1318
                	identifier = new Identifier();
1319
                	identifier.setValue(value[0]);
1320
                }
1321 6273 leinfelder
                else if(name.equals("replicaStatus") && value != null)
1322 6264 leinfelder
                {
1323 6273 leinfelder
                    if(value != null &&
1324
                       value.length > 0 &&
1325 7462 leinfelder
                       (value[0].equalsIgnoreCase("false") || value[0].equalsIgnoreCase("no")))
1326 6273 leinfelder
                    {
1327 7462 leinfelder
                        replicaStatus = false;
1328 6273 leinfelder
                    }
1329 6264 leinfelder
                }
1330 6273 leinfelder
                else if(name.equals("start") && value != null)
1331 6264 leinfelder
                {
1332 6273 leinfelder
                    start = new Integer(value[0]).intValue();
1333 6264 leinfelder
                }
1334 6273 leinfelder
                else if(name.equals("count") && value != null)
1335 6264 leinfelder
                {
1336 6273 leinfelder
                    count = new Integer(value[0]).intValue();
1337 6264 leinfelder
                }
1338
            }
1339 6273 leinfelder
            //make the crud call
1340
            logMetacat.debug("session: " + session + " startTime: " + startTime +
1341 7100 leinfelder
                    " endTime: " + endTime + " formatId: " +
1342
                    formatId + " replicaStatus: " + replicaStatus +
1343 6273 leinfelder
                    " start: " + start + " count: " + count);
1344
1345
            ObjectList ol =
1346 6542 leinfelder
           	 MNodeService.getInstance(request).listObjects(session, startTime, endTime,
1347 8810 leinfelder
           			formatId, identifier, replicaStatus, start, count);
1348 6352 cjones
1349 6273 leinfelder
            out = response.getOutputStream();
1350
            response.setStatus(200);
1351
            response.setContentType("text/xml");
1352
            // Serialize and write it to the output stream
1353 6367 leinfelder
            TypeMarshaller.marshalTypeToOutputStream(ol, out);
1354 6273 leinfelder
1355 6264 leinfelder
        }
1356 6273 leinfelder
1357 6264 leinfelder
    }
1358
1359 6273 leinfelder
1360 6264 leinfelder
    /**
1361 7855 leinfelder
     * Retrieve data package as Bagit zip
1362
     * @param pid
1363
     * @throws NotImplemented
1364
     * @throws NotFound
1365
     * @throws NotAuthorized
1366
     * @throws ServiceFailure
1367
     * @throws InvalidToken
1368
     * @throws IOException
1369 8810 leinfelder
     * @throws InvalidRequest
1370 7855 leinfelder
     */
1371 8810 leinfelder
    protected void getPackage(String format, String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, InvalidRequest {
1372 7855 leinfelder
1373
        Identifier id = new Identifier();
1374
        id.setValue(pid);
1375 8810 leinfelder
        ObjectFormatIdentifier formatId = null;
1376
        if (format != null) {
1377
        	formatId = new ObjectFormatIdentifier();
1378
        	formatId.setValue(format);
1379
        }
1380
		InputStream is = MNodeService.getInstance(request).getPackage(session, formatId , id);
1381 7855 leinfelder
1382 8160 leinfelder
        // use the provided filename
1383
        String filename = null;
1384
        if (is instanceof DeleteOnCloseFileInputStream) {
1385
            filename = ((DeleteOnCloseFileInputStream)is).getFile().getName();
1386
        } else {
1387
        	filename = "dataPackage-" + System.currentTimeMillis() + ".zip";
1388
        }
1389 8034 leinfelder
        response.setHeader("Content-Disposition", "inline; filename=" + filename);
1390 7855 leinfelder
        response.setContentType("application/zip");
1391
        response.setStatus(200);
1392
        OutputStream out = response.getOutputStream();
1393
1394
        // write it to the output stream
1395
        IOUtils.copyLarge(is, out);
1396
   }
1397
1398 7864 leinfelder
	protected void publish(String pid) throws InvalidToken, ServiceFailure,
1399
			NotAuthorized, NotFound, NotImplemented, IOException,
1400
			JiBXException, InvalidRequest, IdentifierNotUnique,
1401
			UnsupportedType, InsufficientResources, InvalidSystemMetadata {
1402
1403
		// publish the object
1404
		Identifier originalIdentifier = new Identifier();
1405
		originalIdentifier.setValue(pid);
1406
		Identifier newIdentifier = MNodeService.getInstance(request).publish(session, originalIdentifier);
1407
1408
		response.setStatus(200);
1409
		response.setContentType("text/xml");
1410
		OutputStream out = response.getOutputStream();
1411
1412
		// write new identifier to the output stream
1413
		TypeMarshaller.marshalTypeToOutputStream(newIdentifier, out);
1414
	}
1415
1416 7855 leinfelder
    /**
1417 6273 leinfelder
     * Retrieve System Metadata
1418 6285 cjones
     * @param pid
1419 6273 leinfelder
     * @throws InvalidToken
1420
     * @throws ServiceFailure
1421
     * @throws NotAuthorized
1422
     * @throws NotFound
1423
     * @throws InvalidRequest
1424
     * @throws NotImplemented
1425
     * @throws IOException
1426
     * @throws JiBXException
1427 6264 leinfelder
     */
1428 6285 cjones
    protected void getSystemMetadataObject(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, InvalidRequest, NotImplemented, IOException, JiBXException {
1429 6273 leinfelder
1430
        Identifier id = new Identifier();
1431 6285 cjones
        id.setValue(pid);
1432 6542 leinfelder
        SystemMetadata sysmeta = MNodeService.getInstance(request).getSystemMetadata(session, id);
1433 6273 leinfelder
1434
        response.setContentType("text/xml");
1435
        response.setStatus(200);
1436
        OutputStream out = response.getOutputStream();
1437
1438
        // Serialize and write it to the output stream
1439 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(sysmeta, out);
1440 6273 leinfelder
   }
1441 6264 leinfelder
1442
1443
    /**
1444
     * Inserts or updates the object
1445
     *
1446 6285 cjones
     * @param pid - ID of data object to be inserted or updated.  If action is update, the pid
1447 6264 leinfelder
     *               is the existing pid.  If insert, the pid is the new one
1448 6269 leinfelder
     * @throws InvalidRequest
1449
     * @throws ServiceFailure
1450
     * @throws JiBXException
1451
     * @throws NotImplemented
1452
     * @throws InvalidSystemMetadata
1453
     * @throws InsufficientResources
1454
     * @throws UnsupportedType
1455
     * @throws IdentifierNotUnique
1456
     * @throws NotAuthorized
1457
     * @throws InvalidToken
1458
     * @throws NotFound
1459 6273 leinfelder
     * @throws IOException
1460 6367 leinfelder
     * @throws IllegalAccessException
1461
     * @throws InstantiationException
1462 6264 leinfelder
     */
1463 6972 leinfelder
    protected void putObject(String trailingPid, String action) throws ServiceFailure, InvalidRequest, JiBXException, InvalidToken, NotAuthorized, IdentifierNotUnique, UnsupportedType, InsufficientResources, InvalidSystemMetadata, NotImplemented, NotFound, IOException, InstantiationException, IllegalAccessException {
1464
1465
    	// Read the incoming data from its Mime Multipart encoding
1466 6269 leinfelder
    	Map<String, File> files = collectMultipartFiles();
1467 6972 leinfelder
1468 6975 leinfelder
    	Identifier pid = new Identifier();
1469 6972 leinfelder
        if (trailingPid == null) {
1470 6975 leinfelder
	        // get the pid string from the body and set the value
1471
	        String pidString = multipartparams.get("pid").get(0);
1472 7051 cjones
	        if (pidString != null) {
1473
            pid.setValue(pidString);
1474
1475
          } else {
1476
              throw new InvalidRequest("1102", "The pid param must be included and contain the identifier.");
1477
1478
          }
1479 6972 leinfelder
        } else {
1480
        	// use the pid included in the URL
1481
        	pid.setValue(trailingPid);
1482
        }
1483
        logMetacat.debug("putObject with pid " + pid.getValue());
1484
        logMetacat.debug("Entering putObject: " + pid.getValue() + "/" + action);
1485
1486 6269 leinfelder
        InputStream object = null;
1487
        InputStream sysmeta = null;
1488
        File smFile = files.get("sysmeta");
1489
        sysmeta = new FileInputStream(smFile);
1490
        File objFile = files.get("object");
1491
        object = new FileInputStream(objFile);
1492
1493 6927 cjones
        // ensure we have the object bytes
1494
        if  ( objFile == null ) {
1495
            throw new InvalidRequest("1102", "The object param must contain the object bytes.");
1496
1497
        }
1498
1499
        // ensure we have the system metadata
1500
        if  ( smFile == null ) {
1501
            throw new InvalidRequest("1102", "The sysmeta param must contain the system metadata document.");
1502
1503
        }
1504
1505 6972 leinfelder
        response.setStatus(200);
1506
        response.setContentType("text/xml");
1507
        OutputStream out = response.getOutputStream();
1508
1509 6269 leinfelder
        if (action.equals(FUNCTION_NAME_INSERT)) {
1510
            // handle inserts
1511
            logMetacat.debug("Commence creation...");
1512 6367 leinfelder
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
1513 6264 leinfelder
1514 6972 leinfelder
            logMetacat.debug("creating object with pid " + pid.getValue());
1515
            Identifier rId = MNodeService.getInstance(request).create(session, pid, object, smd);
1516 6367 leinfelder
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
1517 6264 leinfelder
1518 6269 leinfelder
        } else if (action.equals(FUNCTION_NAME_UPDATE)) {
1519
        	// handle updates
1520
1521
            // construct pids
1522 6972 leinfelder
            Identifier newPid = null;
1523 6269 leinfelder
            try {
1524
            	String newPidString = multipartparams.get("newPid").get(0);
1525 6975 leinfelder
            	newPid = new Identifier();
1526
            	newPid.setValue(newPidString);
1527 6269 leinfelder
            } catch (Exception e) {
1528 6972 leinfelder
				logMetacat.error("Could not get newPid from request");
1529 6269 leinfelder
			}
1530
            logMetacat.debug("Commence update...");
1531
1532
            // get the systemmetadata object
1533 6367 leinfelder
            SystemMetadata smd = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
1534 6264 leinfelder
1535 6972 leinfelder
            Identifier rId = MNodeService.getInstance(request).update(session, pid, object, newPid, smd);
1536 6367 leinfelder
            TypeMarshaller.marshalTypeToOutputStream(rId, out);
1537 6269 leinfelder
        } else {
1538
            throw new InvalidRequest("1000", "Operation must be create or update.");
1539
        }
1540 6972 leinfelder
1541 6264 leinfelder
    }
1542
1543
    /**
1544
     * Handle delete
1545 6285 cjones
     * @param pid ID of data object to be deleted
1546 6264 leinfelder
     * @throws IOException
1547 6273 leinfelder
     * @throws InvalidRequest
1548
     * @throws NotImplemented
1549
     * @throws NotFound
1550
     * @throws NotAuthorized
1551
     * @throws ServiceFailure
1552
     * @throws InvalidToken
1553
     * @throws JiBXException
1554 6264 leinfelder
     */
1555 6285 cjones
    private void deleteObject(String pid) throws IOException, InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, InvalidRequest, JiBXException
1556 6264 leinfelder
    {
1557
1558
        OutputStream out = response.getOutputStream();
1559
        response.setStatus(200);
1560
        response.setContentType("text/xml");
1561
1562
        Identifier id = new Identifier();
1563 6285 cjones
        id.setValue(pid);
1564 6273 leinfelder
1565
        logMetacat.debug("Calling delete");
1566 6542 leinfelder
        MNodeService.getInstance(request).delete(session, id);
1567 6367 leinfelder
        TypeMarshaller.marshalTypeToOutputStream(id, out);
1568 6273 leinfelder
1569 7153 leinfelder
    }
1570
1571
    /**
1572
     * Archives the given pid
1573
     * @param pid
1574
     * @throws InvalidToken
1575
     * @throws ServiceFailure
1576
     * @throws NotAuthorized
1577
     * @throws NotFound
1578
     * @throws NotImplemented
1579
     * @throws IOException
1580
     * @throws JiBXException
1581
     */
1582
    private void archive(String pid) throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, NotImplemented, IOException, JiBXException {
1583 6264 leinfelder
1584 7153 leinfelder
        OutputStream out = response.getOutputStream();
1585
        response.setStatus(200);
1586
        response.setContentType("text/xml");
1587
1588
        Identifier id = new Identifier();
1589
        id.setValue(pid);
1590
1591 7154 leinfelder
        logMetacat.debug("Calling archive");
1592 7153 leinfelder
        MNodeService.getInstance(request).archive(session, id);
1593
1594
        TypeMarshaller.marshalTypeToOutputStream(id, out);
1595
1596
    }
1597
1598 6514 leinfelder
	protected SynchronizationFailed collectSynchronizationFailed() throws IOException, ServiceFailure, InvalidRequest, JiBXException, InstantiationException, IllegalAccessException, ParserConfigurationException, SAXException  {
1599
1600
		// Read the incoming data from its Mime Multipart encoding
1601
		logMetacat.debug("Disassembling MIME multipart form");
1602
		InputStream sf = null;
1603
1604
		// handle MMP inputs
1605
		File tmpDir = getTempDirectory();
1606
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
1607
		MultipartRequestResolver mrr =
1608 9099 jones
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), MAX_UPLOAD_SIZE, 0);
1609 6514 leinfelder
		MultipartRequest mr = null;
1610
		try {
1611
			mr = mrr.resolveMultipart(request);
1612
		} catch (Exception e) {
1613
			throw new ServiceFailure("2161",
1614
					"Could not resolve multipart: " + e.getMessage());
1615
		}
1616
		logMetacat.debug("resolved multipart request");
1617
		Map<String, File> files = mr.getMultipartFiles();
1618
		if (files == null || files.keySet() == null) {
1619
			throw new InvalidRequest("2163",
1620
					"must have multipart file with name 'message'");
1621
		}
1622
		logMetacat.debug("got multipart files");
1623
1624
		multipartparams = mr.getMultipartParameters();
1625
1626
		File sfFile = files.get("message");
1627
		if (sfFile == null) {
1628
			throw new InvalidRequest("2163",
1629
					"Missing the required file-part 'message' from the multipart request.");
1630
		}
1631
		logMetacat.debug("sfFile: " + sfFile.getAbsolutePath());
1632
		sf = new FileInputStream(sfFile);
1633
1634
		SynchronizationFailed syncFailed = (SynchronizationFailed) ExceptionHandler.deserializeXml(sf, "Error deserializing exception");
1635
		return syncFailed;
1636
	}
1637 9122 tao
1638
	/**
1639
	 * Update the system metadata for a specified identifier
1640
	 * @throws ServiceFailure
1641
	 * @throws InvalidRequest
1642
	 * @throws InstantiationException
1643
	 * @throws IllegalAccessException
1644
	 * @throws IOException
1645
	 * @throws JiBXException
1646
	 * @throws NotImplemented
1647
	 * @throws NotAuthorized
1648
	 * @throws InvalidSystemMetadata
1649
	 * @throws InvalidToken
1650
	 */
1651
	protected void updateSystemMetadata() throws ServiceFailure, InvalidRequest,
1652
	                        InstantiationException, IllegalAccessException, IOException, JiBXException, NotImplemented,
1653
	                        NotAuthorized, InvalidSystemMetadata, InvalidToken {
1654
	    // Read the incoming data from its Mime Multipart encoding
1655
        Map<String, File> files = collectMultipartFiles();
1656
1657
        // get the encoded pid string from the body and make the object
1658
        String pidString = multipartparams.get("pid").get(0);
1659
        Identifier pid = new Identifier();
1660
        pid.setValue(pidString);
1661
1662
        logMetacat.debug("updateSystemMetadata: " + pid);
1663 6514 leinfelder
1664 9122 tao
        // get the system metadata from the request
1665
        File smFile = files.get("sysmeta");
1666
        FileInputStream sysmeta = new FileInputStream(smFile);
1667
        SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
1668
1669
        logMetacat.debug("updating system metadata with pid " + pid.getValue());
1670
1671
        MNodeService.getInstance(request).updateSystemMetadata(session, pid, systemMetadata);
1672
	}
1673
1674 6264 leinfelder
}