Project

General

Profile

1 5211 jones
/**
2
 *  '$RCSfile$'
3 5805 berkley
 *  Copyright: 2011 Regents of the University of California and the
4 5211 jones
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: Serhan AKIN $'
7
 *     '$Date: 2009-06-13 15:28:13 +0300  $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.restservice;
24
25 6130 leinfelder
import java.io.File;
26 6269 leinfelder
import java.io.FileInputStream;
27 6590 cjones
import java.io.FileNotFoundException;
28 6130 leinfelder
import java.io.IOException;
29
import java.io.InputStream;
30
import java.io.OutputStream;
31
import java.io.PrintWriter;
32
import java.util.Enumeration;
33
import java.util.Hashtable;
34 6269 leinfelder
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37 6130 leinfelder
import java.util.Timer;
38 5211 jones
39
import javax.servlet.ServletContext;
40
import javax.servlet.http.HttpServletRequest;
41
import javax.servlet.http.HttpServletResponse;
42 6514 leinfelder
import javax.xml.parsers.ParserConfigurationException;
43 6067 rnahf
44 6269 leinfelder
import org.apache.commons.fileupload.FileUploadException;
45 5299 jones
import org.apache.commons.io.IOUtils;
46 5211 jones
import org.apache.log4j.Logger;
47 6244 leinfelder
import org.dataone.client.auth.CertificateManager;
48 6269 leinfelder
import org.dataone.mimemultipart.MultipartRequest;
49
import org.dataone.mimemultipart.MultipartRequestResolver;
50 5299 jones
import org.dataone.service.exceptions.BaseException;
51 6269 leinfelder
import org.dataone.service.exceptions.InvalidRequest;
52
import org.dataone.service.exceptions.ServiceFailure;
53 6514 leinfelder
import org.dataone.service.types.v1.AccessPolicy;
54 6590 cjones
import org.dataone.service.types.v1.Replica;
55
import org.dataone.service.types.v1.ReplicationPolicy;
56 6366 leinfelder
import org.dataone.service.types.v1.Session;
57
import org.dataone.service.types.v1.SystemMetadata;
58 6860 cjones
import org.dataone.service.util.ExceptionHandler;
59 6367 leinfelder
import org.dataone.service.util.TypeMarshaller;
60 5320 jones
import org.jibx.runtime.JiBXException;
61 6514 leinfelder
import org.xml.sax.SAXException;
62 5211 jones
63
import edu.ucsb.nceas.metacat.MetacatHandler;
64 5637 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
65 6793 cjones
import edu.ucsb.nceas.utilities.Log;
66 5637 berkley
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
67 5211 jones
/**
68
 *
69 6268 leinfelder
 * Base class for handling D1 REST calls in Metacat
70 5211 jones
 *
71 6268 leinfelder
 * @author leinfelder
72 5211 jones
 */
73 6267 leinfelder
public class D1ResourceHandler {
74 5211 jones
75
    /**HTTP Verb GET*/
76
    public static final byte GET = 1;
77
    /**HTTP Verb POST*/
78
    public static final byte POST = 2;
79
    /**HTTP Verb PUT*/
80
    public static final byte PUT = 3;
81
    /**HTTP Verb DELETE*/
82
    public static final byte DELETE = 4;
83 5651 berkley
    /**HTTP Verb HEAD*/
84
    public static final byte HEAD = 5;
85 5211 jones
86
    /*
87
     * API Resources
88
     */
89 6271 leinfelder
    protected static final String RESOURCE_BASE_URL = "d1";
90
91 6247 leinfelder
    protected static final String RESOURCE_OBJECTS = "object";
92
    protected static final String RESOURCE_META = "meta";
93
    protected static final String RESOURCE_LOG = "log";
94
    protected static final String RESOURCE_CHECKSUM = "checksum";
95 6249 leinfelder
96
    protected static final String RESOURCE_IS_AUTHORIZED = "isAuthorized";
97
    protected static final String RESOURCE_ACCESS_RULES = "accessRules";
98 5211 jones
99 6590 cjones
100 5211 jones
    /*
101
     * API Functions used as URL parameters
102
     */
103 6247 leinfelder
    protected static final String FUNCTION_NAME_INSERT = "insert";
104
    protected static final String FUNCTION_NAME_UPDATE = "update";
105 5414 berkley
106 6247 leinfelder
    protected ServletContext servletContext;
107
    protected Logger logMetacat;
108
    protected MetacatHandler handler;
109
    protected HttpServletRequest request;
110
    protected HttpServletResponse response;
111 5211 jones
112 6247 leinfelder
    protected Hashtable<String, String[]> params;
113 6269 leinfelder
    protected Map<String, List<String>> multipartparams;
114 6244 leinfelder
115
    // D1 certificate-based authentication
116 6247 leinfelder
    protected Session session;
117 5211 jones
118
    /**Initializes new instance by setting servlet context,request and response*/
119 6267 leinfelder
    public D1ResourceHandler(ServletContext servletContext,
120 5211 jones
            HttpServletRequest request, HttpServletResponse response) {
121
        this.servletContext = servletContext;
122
        this.request = request;
123
        this.response = response;
124
    }
125
126
    /**
127 6268 leinfelder
     * This function is called from REST API servlet and handles each request
128 5211 jones
     *
129
     * @param httpVerb (GET, POST, PUT or DELETE)
130
     */
131
    public void handle(byte httpVerb) {
132 6267 leinfelder
        logMetacat = Logger.getLogger(D1ResourceHandler.class);
133 5211 jones
        try {
134 6268 leinfelder
135 6244 leinfelder
            // load session from certificate in request
136
            session = CertificateManager.getInstance().getSession(request);
137 5211 jones
138 6268 leinfelder
            // initialize the parameters
139
            params = new Hashtable<String, String[]>();
140
            initParams();
141 5211 jones
142 6268 leinfelder
            // create the handler for interacting with Metacat
143
            Timer timer = new Timer();
144
            handler = new MetacatHandler(timer);
145 5211 jones
146
        } catch (Exception e) {
147 6268 leinfelder
        	// TODO: more D1 structure when failing here
148
        	response.setStatus(400);
149
            printError("Incorrect resource!", response);
150
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
151 5211 jones
        }
152
    }
153 5374 berkley
154 6514 leinfelder
    protected String parseTrailing(String resource, String token) {
155
    	// get the rest
156
        String extra = null;
157
        if (resource.indexOf(token) != -1) {
158
        	// what comes after the token?
159
            extra = resource.substring(resource.indexOf(token) + token.length());
160
            // remove the slash
161
            if (extra.startsWith("/")) {
162
            	extra = extra.substring(1);
163
            }
164
            // is there anything left?
165
            if (extra.length() == 0) {
166
            	extra = null;
167
            }
168
        }
169
        return extra;
170
    }
171 6590 cjones
172
    /**
173 6793 cjones
     * Parse the BaseException information for replication status failures if any
174
     *
175
     * @return failure  the BaseException failure, one of it's subclasses, or null
176
     * @throws ServiceFailure
177
     * @throws InvalidRequest
178
     * @throws JiBXException
179
     * @throws IllegalAccessException
180
     * @throws InstantiationException
181
     * @throws IOException
182
     */
183
    protected BaseException collectReplicationStatus()
184
        throws ServiceFailure, InvalidRequest, IOException,
185
        InstantiationException, IllegalAccessException, JiBXException {
186
187
        BaseException failure = null;
188
        File tmpDir = getTempDirectory();
189
        MultipartRequest mr = null;
190
        Map<String, File> mmFileParts = null;
191
        File exceptionFile = null;
192
        InputStream exceptionFileStream = null;
193
194
        // Read the incoming data from its Mime Multipart encoding
195
        logMetacat.debug("Parsing BaseException from the mime multipart entity");
196
197
        // handle MMP inputs
198
        MultipartRequestResolver mrr =
199
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
200
201
        try {
202
            mr = mrr.resolveMultipart(request);
203
            logMetacat.debug("Resolved the replication status BaseException multipart request.");
204
205
        } catch (IOException e) {
206
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
207
                e.getMessage());
208
209
        } catch (FileUploadException e) {
210
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
211
                e.getMessage());
212
213
        } catch (Exception e) {
214
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
215
                e.getMessage());
216
217
        }
218
219
        // get the map of file parts
220
        mmFileParts = mr.getMultipartFiles();
221
222
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
223
            logMetacat.debug("BaseException for setReplicationStatus is null");
224
        }
225
226
        multipartparams = mr.getMultipartParameters();
227
        exceptionFile = mmFileParts.get("failure");
228
229
        if ( exceptionFile != null ) {
230
231 6860 cjones
            // deserialize the BaseException subclass
232 6793 cjones
            exceptionFileStream = new FileInputStream(exceptionFile);
233 6860 cjones
            try {
234
                failure = ExceptionHandler.deserializeXml(exceptionFileStream,
235
                    "Replication failed for an unknown reason.");
236 6793 cjones
237 6860 cjones
            } catch (ParserConfigurationException e) {
238
                throw new ServiceFailure("4700", "Couldn't parse the replication failure exception: " +
239
                        e.getMessage());
240
241
            } catch (SAXException e) {
242
                throw new ServiceFailure("4700", "Couldn't traverse the replication failure exception: " +
243
                        e.getMessage());
244
245
            }
246
247 6793 cjones
        }
248
249
250
        return failure;
251
252
    }
253
254
    /**
255 6590 cjones
     * Parse the replication policy document out of the mime-multipart form data
256
     *
257
     * @return policy  the encoded policy
258
     * @throws ServiceFailure
259
     * @throws InvalidRequest
260
     * @throws IOException
261
     * @throws InstantiationException
262
     * @throws IllegalAccessException
263
     * @throws JiBXException
264
     */
265
    protected ReplicationPolicy collectReplicationPolicy()
266
        throws ServiceFailure, InvalidRequest, IOException, InstantiationException,
267
        IllegalAccessException, JiBXException {
268
269
        ReplicationPolicy policy = null;
270
        File tmpDir = getTempDirectory();
271
        MultipartRequest mr = null;
272
        Map<String, File> mmFileParts = null;
273
        File replPolicyFile = null;
274
        InputStream replPolicyStream = null;
275
276
        // Read the incoming data from its Mime Multipart encoding
277
        logMetacat.debug("Parsing ReplicationPolicy from the mime multipart entity");
278
279
        // handle MMP inputs
280
        MultipartRequestResolver mrr =
281
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
282
283
        try {
284
            mr = mrr.resolveMultipart(request);
285
            logMetacat.debug("Resolved the ReplicationPolicy multipart request.");
286
287
        } catch (IOException e) {
288
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
289
                e.getMessage());
290
291
        } catch (FileUploadException e) {
292
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
293 6793 cjones
                e.getMessage());
294 6590 cjones
295
        } catch (Exception e) {
296
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
297 6793 cjones
                e.getMessage());
298 6590 cjones
299
        }
300
301
        // get the map of file parts
302
        mmFileParts = mr.getMultipartFiles();
303
304
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
305
            throw new InvalidRequest("4883", "The multipart request must include " +
306
                "a file with the name 'policy'.");
307
308
        }
309
310
        multipartparams = mr.getMultipartParameters();
311
        replPolicyFile = mmFileParts.get("policy");
312
313
        if ( replPolicyFile == null ) {
314
            throw new InvalidRequest("4883", "The multipart request must include " +
315
            "a file with the name 'policy'.");
316
317
        }
318
319
320
        // deserialize the ReplicationPolicy
321
        replPolicyStream = new FileInputStream(replPolicyFile);
322
        policy = TypeMarshaller.unmarshalTypeFromStream(ReplicationPolicy.class, replPolicyStream);
323
324
        return policy;
325
326
    }
327
328
    /**
329
     * Parse the replica metadata document out of the mime-multipart form data
330
     *
331
     * @return replica  the encoded replica
332
     * @throws ServiceFailure
333
     * @throws InvalidRequest
334
     * @throws IOException
335
     * @throws InstantiationException
336
     * @throws IllegalAccessException
337
     * @throws JiBXException
338
     */
339
    protected Replica collectReplicaMetadata()
340
        throws ServiceFailure, InvalidRequest {
341
342
        Replica replica = null;
343
        File tmpDir = getTempDirectory();
344
        MultipartRequest mr = null;
345
        Map<String, File> mmFileParts = null;
346
        File replicaFile = null;
347
        InputStream replicaStream = null;
348
349
        // Read the incoming data from its Mime Multipart encoding
350
        logMetacat.debug("Parsing Replica from the mime multipart entity");
351
352
        // handle MMP inputs
353
        MultipartRequestResolver mrr =
354
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
355
356
        try {
357
            mr = mrr.resolveMultipart(request);
358
            logMetacat.debug("Resolved the Replica multipart request.");
359
360
        } catch (IOException e) {
361
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
362
                e.getMessage());
363
364
        } catch (FileUploadException e) {
365
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
366
                    e.getMessage());
367
368
        } catch (Exception e) {
369
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
370
                    e.getMessage());
371
372
        }
373
374
        // get the map of file parts
375
        mmFileParts = mr.getMultipartFiles();
376
377
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
378
            throw new InvalidRequest("4853", "The multipart request must include " +
379
                "a file with the name 'replicaMetadata'.");
380
381
        }
382
383
        multipartparams = mr.getMultipartParameters();
384
        replicaFile = mmFileParts.get("replicaMetadata");
385
386
        if ( replicaFile == null ) {
387
            throw new InvalidRequest("4853", "The multipart request must include " +
388
            "a file with the name 'replicaMetadata'.");
389
390
        }
391
392
393
        // deserialize the ReplicationPolicy
394
        try {
395
            replicaStream = new FileInputStream(replicaFile);
396
        } catch (FileNotFoundException e) {
397
            throw new ServiceFailure("4852", "Couldn't find the multipart file: " +
398
                    e.getMessage());
399
400
        }
401
402
        try {
403
            replica = TypeMarshaller.unmarshalTypeFromStream(Replica.class, replicaStream);
404
        } catch (IOException e) {
405
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
406
                    e.getMessage());
407
408
        } catch (InstantiationException e) {
409
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
410
                    e.getMessage());
411
412
        } catch (IllegalAccessException e) {
413
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
414
                    e.getMessage());
415
416
        } catch (JiBXException e) {
417
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
418
                    e.getMessage());
419
420
        }
421
422
        return replica;
423
424
    }
425 6514 leinfelder
426 6590 cjones
    protected AccessPolicy collectAccessPolicy()
427
        throws IOException, ServiceFailure, InvalidRequest, JiBXException,
428
        InstantiationException, IllegalAccessException, ParserConfigurationException,
429
        SAXException  {
430 6514 leinfelder
431
		// Read the incoming data from its Mime Multipart encoding
432
		logMetacat.debug("Disassembling MIME multipart form");
433
		InputStream ap = null;
434
435
		// handle MMP inputs
436
		File tmpDir = getTempDirectory();
437
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
438
		MultipartRequestResolver mrr =
439
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
440
		MultipartRequest mr = null;
441
		try {
442
			mr = mrr.resolveMultipart(request);
443
		} catch (Exception e) {
444
			throw new ServiceFailure("2161",
445
					"Could not resolve multipart: " + e.getMessage());
446
		}
447
		logMetacat.debug("resolved multipart request");
448
		Map<String, File> files = mr.getMultipartFiles();
449
		if (files == null || files.keySet() == null) {
450
			throw new InvalidRequest("2163",
451
					"must have multipart file with name 'accessPolicy'");
452
		}
453
		logMetacat.debug("got multipart files");
454
455
		multipartparams = mr.getMultipartParameters();
456
457
		File apFile = files.get("accessPolicy");
458
		if (apFile == null) {
459
			throw new InvalidRequest("2163",
460
					"Missing the required file-part 'accessPolicy' from the multipart request.");
461
		}
462
		logMetacat.debug("apFile: " + apFile.getAbsolutePath());
463
		ap = new FileInputStream(apFile);
464
465
		AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromStream(AccessPolicy.class, ap);
466
		return accessPolicy;
467
	}
468
469 6590 cjones
    protected SystemMetadata collectSystemMetadata()
470
        throws IOException, FileUploadException, ServiceFailure, InvalidRequest,
471
        JiBXException, InstantiationException, IllegalAccessException  {
472 6269 leinfelder
473
		// Read the incoming data from its Mime Multipart encoding
474
		logMetacat.debug("Disassembling MIME multipart form");
475
		InputStream sysmeta = null;
476
477
		// handle MMP inputs
478
		File tmpDir = getTempDirectory();
479
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
480
		MultipartRequestResolver mrr =
481
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
482
		MultipartRequest mr = null;
483
		try {
484
			mr = mrr.resolveMultipart(request);
485
		} catch (Exception e) {
486
			throw new ServiceFailure("1202",
487
					"Could not resolve multipart: " + e.getMessage());
488
		}
489
		logMetacat.debug("resolved multipart request");
490
		Map<String, File> files = mr.getMultipartFiles();
491
		if (files == null) {
492
			throw new ServiceFailure("1202",
493
					"register meta must have multipart file with name 'sysmeta'");
494
		}
495
		logMetacat.debug("got multipart files");
496
497
		if (files.keySet() == null) {
498
			logMetacat.error("No file keys in MMP request.");
499
			throw new ServiceFailure(
500
					"1202",
501
					"No file keys found in MMP.  "
502
							+ "register meta must have multipart file with name 'sysmeta'");
503
		}
504
505
		// for logging purposes, dump out the key-value pairs that
506
		// constitute the request
507
		// 3 types exist: request params, multipart params, and
508
		// multipart files
509
		Iterator it = files.keySet().iterator();
510
		logMetacat.debug("iterating through request parts: " + it);
511
		while (it.hasNext()) {
512
			String key = (String) it.next();
513
			logMetacat.debug("files key: " + key);
514
			logMetacat.debug("files value: " + files.get(key));
515
		}
516
517
		multipartparams = mr.getMultipartParameters();
518
		it = multipartparams.keySet().iterator();
519
		while (it.hasNext()) {
520
			String key = (String) it.next();
521
			logMetacat.debug("multipartparams key: " + key);
522
			logMetacat.debug("multipartparams value: " + multipartparams.get(key));
523
		}
524
525
		it = params.keySet().iterator();
526
		while (it.hasNext()) {
527
			String key = (String) it.next();
528
			logMetacat.debug("param key: " + key);
529
			logMetacat.debug("param value: " + params.get(key));
530
		}
531
		logMetacat.debug("done iterating the request...");
532
533
		File smFile = files.get("sysmeta");
534
		if (smFile == null) {
535
			throw new InvalidRequest("1102",
536
					"Missing the required file-part 'sysmeta' from the multipart request.");
537
		}
538
		logMetacat.debug("smFile: " + smFile.getAbsolutePath());
539
		sysmeta = new FileInputStream(smFile);
540
541
		logMetacat.debug("Commence creation...");
542 6367 leinfelder
		SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
543 6269 leinfelder
		return systemMetadata;
544
	}
545
546 6590 cjones
    protected Map<String, File> collectMultipartFiles()
547
        throws ServiceFailure, InvalidRequest {
548 6269 leinfelder
549
        // Read the incoming data from its Mime Multipart encoding
550
        logMetacat.debug("Disassembling MIME multipart form");
551
        InputStream object = null;
552
        InputStream sysmeta = null;
553
554
555
        // handle MMP inputs
556
        File tmpDir = getTempDirectory();
557 6272 leinfelder
        logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
558 6269 leinfelder
        MultipartRequestResolver mrr =
559
        	new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
560
        MultipartRequest mr = null;
561
		try {
562
			mr = mrr.resolveMultipart(request);
563
		} catch (Exception e) {
564
            throw new ServiceFailure("1202",
565
            		"Could not resolve multipart files: " + e.getMessage());
566
		}
567 6272 leinfelder
        logMetacat.debug("resolved multipart request");
568 6269 leinfelder
        Map<String, File> files = mr.getMultipartFiles();
569
        if (files == null) {
570
            throw new ServiceFailure("1202", "create/update must have multipart files with names 'object' and 'sysmeta'");
571
        }
572 6272 leinfelder
        logMetacat.debug("got multipart files");
573 6269 leinfelder
574
        if (files.keySet() == null) {
575 6272 leinfelder
            logMetacat.error("No file keys in MMP request.");
576 6269 leinfelder
            throw new ServiceFailure("1202", "No file keys found in MMP.  " +
577
                    "create/update must have multipart files with names 'object' and 'sysmeta'");
578
        }
579
580
		// for logging purposes, dump out the key-value pairs that constitute the request
581
		// 3 types exist: request params, multipart params, and multipart files
582
        Iterator it = files.keySet().iterator();
583 6272 leinfelder
        logMetacat.debug("iterating through files");
584 6269 leinfelder
        while (it.hasNext()) {
585
            String key = (String)it.next();
586 6272 leinfelder
            logMetacat.debug("files key: " + key);
587
            logMetacat.debug("files value: " + files.get(key));
588 6269 leinfelder
        }
589
590
        multipartparams = mr.getMultipartParameters();
591
        it = multipartparams.keySet().iterator();
592 6272 leinfelder
        logMetacat.debug("iterating through multipartparams");
593 6269 leinfelder
        while (it.hasNext()) {
594
            String key = (String)it.next();
595 6272 leinfelder
            logMetacat.debug("multipartparams key: " + key);
596
            logMetacat.debug("multipartparams value: " + multipartparams.get(key));
597 6269 leinfelder
        }
598
599
        it = params.keySet().iterator();
600 6272 leinfelder
        logMetacat.debug("iterating through params");
601 6269 leinfelder
        while (it.hasNext()) {
602
            String key = (String)it.next();
603 6272 leinfelder
            logMetacat.debug("param key: " + key);
604
            logMetacat.debug("param value: " + params.get(key));
605 6269 leinfelder
        }
606 6272 leinfelder
        logMetacat.debug("done iterating the request...");
607 6269 leinfelder
608
        File smFile = files.get("sysmeta");
609
		if (smFile == null) {
610
		    throw new InvalidRequest("1102", "Missing the required file-part 'sysmeta' from the multipart request.");
611
		}
612 6272 leinfelder
        logMetacat.debug("smFile: " + smFile.getAbsolutePath());
613 6269 leinfelder
        File objFile = files.get("object");
614
		if (objFile == null) {
615
		    throw new InvalidRequest("1102", "Missing the required file-part 'object' from the multipart request.");
616
		}
617 6272 leinfelder
        logMetacat.debug("objectfile: " + objFile.getAbsolutePath());
618 6269 leinfelder
619
        return files;
620
    }
621
622 6140 cjones
		/**
623 6590 cjones
     *  copies request parameters to a hashtable which is given as argument to
624
     *  native metacathandler functions
625 5374 berkley
     */
626 6247 leinfelder
    protected void initParams() {
627 5211 jones
628 5374 berkley
        String name = null;
629
        String[] value = null;
630
        Enumeration paramlist = request.getParameterNames();
631
        while (paramlist.hasMoreElements()) {
632
            name = (String) paramlist.nextElement();
633
            value = request.getParameterValues(name);
634
            params.put(name, value);
635
        }
636
    }
637 6660 leinfelder
638
    /**
639
     * Collect the multipart params from the request
640
     * @throws Exception
641
     */
642
	protected void initMultipartParams() throws Exception {
643
644
		// Read the incoming data from its Mime Multipart encoding
645
		logMetacat.debug("Disassembling MIME multipart form");
646
647
		// handle MMP inputs
648
		File tmpDir = getTempDirectory();
649
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
650
		MultipartRequestResolver mrr =
651
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
652
		MultipartRequest mr = mrr.resolveMultipart(request);
653
654
		multipartparams = mr.getMultipartParameters();
655
	}
656 6469 leinfelder
657 5211 jones
    /**
658 5808 berkley
     * locate the boundary marker for an MMP
659 5462 berkley
     * @param is
660
     * @return
661 5808 berkley
     * @throws IOException
662 5462 berkley
     */
663 5639 berkley
    protected static String[] findBoundaryString(InputStream is)
664 6268 leinfelder
        throws IOException {
665 5639 berkley
        String[] endResult = new String[2];
666 5637 berkley
        String boundary = "";
667 5639 berkley
        String searchString = "boundary=";
668 5637 berkley
        byte[] b = new byte[1024];
669 5639 berkley
        int numbytes = is.read(b, 0, 1024);
670 5826 berkley
671 5639 berkley
        while(numbytes != -1)
672 5636 berkley
        {
673 5639 berkley
            String s = new String(b, 0, numbytes);
674 5826 berkley
            int searchStringIndex = s.indexOf(searchString);
675 5639 berkley
676
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
677
            { //the end of the boundary is in the next byte array
678
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
679
            }
680
            else if(!boundary.startsWith("--"))
681
            { //we can read the whole boundary from this byte array
682
                boundary = s.substring(searchStringIndex + searchString.length() + 1,
683
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
684
                boundary = "--" + boundary;
685
                endResult[0] = boundary;
686
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
687
                        s.length());
688
                break;
689
            }
690
            else
691
            { //we're now reading the 2nd byte array to get the rest of the boundary
692
                searchString = "\"";
693
                searchStringIndex = s.indexOf(searchString);
694
                boundary += s.substring(0, searchStringIndex);
695
                boundary = "--" + boundary;
696
                endResult[0] = boundary;
697
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
698
                        s.length());
699
                break;
700
            }
701 5637 berkley
        }
702 5639 berkley
        return endResult;
703
    }
704
705 5808 berkley
    /**
706 5838 berkley
     * return the directory where temp files are stored
707
     * @return
708
     */
709 6248 leinfelder
    protected static File getTempDirectory()
710 5838 berkley
    {
711
        File tmpDir = null;
712 6267 leinfelder
        Logger logMetacat = Logger.getLogger(D1ResourceHandler.class);
713 6268 leinfelder
        try {
714 5639 berkley
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
715
        }
716 6268 leinfelder
        catch(PropertyNotFoundException pnfe) {
717 6267 leinfelder
            logMetacat.error("D1ResourceHandler.writeMMPPartstoFiles: " +
718 5639 berkley
                    "application.tmpDir not found.  Using /tmp instead.");
719
            tmpDir = new File("/tmp");
720
        }
721 5838 berkley
        return tmpDir;
722 5639 berkley
    }
723
724 5637 berkley
    /**
725 5211 jones
     * Prints xml response
726
     * @param message Message to be displayed
727
     * @param response Servlet response that xml message will be printed
728
     * */
729 6247 leinfelder
    protected void printError(String message, HttpServletResponse response) {
730 5211 jones
        try {
731 6267 leinfelder
            logMetacat.error("D1ResourceHandler: Printing error to servlet response: " + message);
732 5211 jones
            PrintWriter out = response.getWriter();
733
            response.setContentType("text/xml");
734
            out.println("<?xml version=\"1.0\"?>");
735
            out.println("<error>");
736
            out.println(message);
737
            out.println("</error>");
738
            out.close();
739
        } catch (IOException e) {
740
            e.printStackTrace();
741
        }
742
    }
743 5370 berkley
744 5692 berkley
    /**
745
     * serialize a D1 exception using jibx
746
     * @param e
747
     * @param out
748
     */
749 6247 leinfelder
    protected void serializeException(BaseException e, OutputStream out) {
750 5319 jones
        // TODO: Use content negotiation to determine which return format to use
751
        response.setContentType("text/xml");
752
        response.setStatus(e.getCode());
753 5512 berkley
754 6267 leinfelder
        logMetacat.error("D1ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
755 5512 berkley
        e.printStackTrace();
756
757 5319 jones
        try {
758
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
759
        } catch (IOException e1) {
760
            logMetacat.error("Error writing exception to stream. "
761
                    + e1.getMessage());
762
        }
763
    }
764
765 5211 jones
}