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
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
66 5211 jones
/**
67
 *
68 6268 leinfelder
 * Base class for handling D1 REST calls in Metacat
69 5211 jones
 *
70 6268 leinfelder
 * @author leinfelder
71 5211 jones
 */
72 6267 leinfelder
public class D1ResourceHandler {
73 5211 jones
74
    /**HTTP Verb GET*/
75
    public static final byte GET = 1;
76
    /**HTTP Verb POST*/
77
    public static final byte POST = 2;
78
    /**HTTP Verb PUT*/
79
    public static final byte PUT = 3;
80
    /**HTTP Verb DELETE*/
81
    public static final byte DELETE = 4;
82 5651 berkley
    /**HTTP Verb HEAD*/
83
    public static final byte HEAD = 5;
84 5211 jones
85
    /*
86
     * API Resources
87
     */
88 6271 leinfelder
    protected static final String RESOURCE_BASE_URL = "d1";
89
90 6247 leinfelder
    protected static final String RESOURCE_OBJECTS = "object";
91
    protected static final String RESOURCE_META = "meta";
92
    protected static final String RESOURCE_LOG = "log";
93 6249 leinfelder
94 7417 leinfelder
    protected static final String RESOURCE_QUERY = "query";
95
96 6249 leinfelder
    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 6994 leinfelder
154
    /**
155
     * subclasses should provide a more useful implementation
156
     * @return
157
     */
158
    protected boolean isD1Enabled() {
159
160
    	return true;
161
    }
162 5374 berkley
163 6514 leinfelder
    protected String parseTrailing(String resource, String token) {
164
    	// get the rest
165
        String extra = null;
166
        if (resource.indexOf(token) != -1) {
167
        	// what comes after the token?
168
            extra = resource.substring(resource.indexOf(token) + token.length());
169
            // remove the slash
170
            if (extra.startsWith("/")) {
171
            	extra = extra.substring(1);
172
            }
173
            // is there anything left?
174
            if (extra.length() == 0) {
175
            	extra = null;
176
            }
177
        }
178
        return extra;
179
    }
180 6590 cjones
181
    /**
182 6793 cjones
     * Parse the BaseException information for replication status failures if any
183
     *
184
     * @return failure  the BaseException failure, one of it's subclasses, or null
185
     * @throws ServiceFailure
186
     * @throws InvalidRequest
187
     * @throws JiBXException
188
     * @throws IllegalAccessException
189
     * @throws InstantiationException
190
     * @throws IOException
191
     */
192
    protected BaseException collectReplicationStatus()
193
        throws ServiceFailure, InvalidRequest, IOException,
194
        InstantiationException, IllegalAccessException, JiBXException {
195
196
        BaseException failure = null;
197
        File tmpDir = getTempDirectory();
198
        MultipartRequest mr = null;
199
        Map<String, File> mmFileParts = null;
200
        File exceptionFile = null;
201
        InputStream exceptionFileStream = null;
202
203
        // Read the incoming data from its Mime Multipart encoding
204
        logMetacat.debug("Parsing BaseException from the mime multipart entity");
205
206
        // handle MMP inputs
207
        MultipartRequestResolver mrr =
208
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
209
210
        try {
211
            mr = mrr.resolveMultipart(request);
212
            logMetacat.debug("Resolved the replication status BaseException multipart request.");
213
214
        } catch (IOException e) {
215
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
216
                e.getMessage());
217
218
        } catch (FileUploadException e) {
219
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
220
                e.getMessage());
221
222
        } catch (Exception e) {
223
            throw new ServiceFailure("4700", "Couldn't resolve the multipart request: " +
224
                e.getMessage());
225
226
        }
227
228
        // get the map of file parts
229
        mmFileParts = mr.getMultipartFiles();
230
231
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
232
            logMetacat.debug("BaseException for setReplicationStatus is null");
233
        }
234
235
        multipartparams = mr.getMultipartParameters();
236
        exceptionFile = mmFileParts.get("failure");
237
238 7065 leinfelder
        if ( exceptionFile != null && exceptionFile.length() > 0 ) {
239 6793 cjones
240 6860 cjones
            // deserialize the BaseException subclass
241 6793 cjones
            exceptionFileStream = new FileInputStream(exceptionFile);
242 6860 cjones
            try {
243
                failure = ExceptionHandler.deserializeXml(exceptionFileStream,
244
                    "Replication failed for an unknown reason.");
245 6793 cjones
246 6860 cjones
            } catch (ParserConfigurationException e) {
247
                throw new ServiceFailure("4700", "Couldn't parse the replication failure exception: " +
248
                        e.getMessage());
249
250
            } catch (SAXException e) {
251
                throw new ServiceFailure("4700", "Couldn't traverse the replication failure exception: " +
252
                        e.getMessage());
253
254
            }
255
256 6793 cjones
        }
257
258
259
        return failure;
260
261
    }
262 7092 cjones
263
    /**
264
     * Parse string parameters from the mime multipart entity of the request.
265
     * Populates the multipartparams map
266
     *
267
     * @throws IOException
268
     * @throws FileUploadException
269
     * @throws Exception
270
     */
271
    protected void collectMultipartParams()
272
        throws IOException, FileUploadException, Exception {
273
274
        File tmpDir = getTempDirectory();
275
        MultipartRequest mr = null;
276
277
        // Read the incoming data from its Mime Multipart encoding
278
        logMetacat.debug("Parsing rights holder info from the mime multipart entity");
279
280
        // handle MMP inputs
281
        MultipartRequestResolver mrr =
282
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
283
284
        mr = mrr.resolveMultipart(request);
285
        logMetacat.debug("Resolved the rights holder info from the mime multipart entity.");
286
287
        // we only have params in this MMP entity
288
        multipartparams = mr.getMultipartParameters();
289
290
    }
291 6793 cjones
292 7092 cjones
293 6793 cjones
    /**
294 6590 cjones
     * Parse the replication policy document out of the mime-multipart form data
295
     *
296
     * @return policy  the encoded policy
297
     * @throws ServiceFailure
298
     * @throws InvalidRequest
299
     * @throws IOException
300
     * @throws InstantiationException
301
     * @throws IllegalAccessException
302
     * @throws JiBXException
303
     */
304
    protected ReplicationPolicy collectReplicationPolicy()
305
        throws ServiceFailure, InvalidRequest, IOException, InstantiationException,
306
        IllegalAccessException, JiBXException {
307
308
        ReplicationPolicy policy = null;
309
        File tmpDir = getTempDirectory();
310
        MultipartRequest mr = null;
311
        Map<String, File> mmFileParts = null;
312
        File replPolicyFile = null;
313
        InputStream replPolicyStream = null;
314
315
        // Read the incoming data from its Mime Multipart encoding
316
        logMetacat.debug("Parsing ReplicationPolicy from the mime multipart entity");
317
318
        // handle MMP inputs
319
        MultipartRequestResolver mrr =
320
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
321
322
        try {
323
            mr = mrr.resolveMultipart(request);
324
            logMetacat.debug("Resolved the ReplicationPolicy multipart request.");
325
326
        } catch (IOException e) {
327
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
328
                e.getMessage());
329
330
        } catch (FileUploadException e) {
331
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
332 6793 cjones
                e.getMessage());
333 6590 cjones
334
        } catch (Exception e) {
335
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
336 6793 cjones
                e.getMessage());
337 6590 cjones
338
        }
339
340
        // get the map of file parts
341
        mmFileParts = mr.getMultipartFiles();
342
343
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
344
            throw new InvalidRequest("4883", "The multipart request must include " +
345
                "a file with the name 'policy'.");
346
347
        }
348
349
        multipartparams = mr.getMultipartParameters();
350
        replPolicyFile = mmFileParts.get("policy");
351
352
        if ( replPolicyFile == null ) {
353
            throw new InvalidRequest("4883", "The multipart request must include " +
354
            "a file with the name 'policy'.");
355
356
        }
357
358
359
        // deserialize the ReplicationPolicy
360
        replPolicyStream = new FileInputStream(replPolicyFile);
361
        policy = TypeMarshaller.unmarshalTypeFromStream(ReplicationPolicy.class, replPolicyStream);
362
363
        return policy;
364
365
    }
366
367
    /**
368
     * Parse the replica metadata document out of the mime-multipart form data
369
     *
370
     * @return replica  the encoded replica
371
     * @throws ServiceFailure
372
     * @throws InvalidRequest
373
     * @throws IOException
374
     * @throws InstantiationException
375
     * @throws IllegalAccessException
376
     * @throws JiBXException
377
     */
378
    protected Replica collectReplicaMetadata()
379
        throws ServiceFailure, InvalidRequest {
380
381
        Replica replica = null;
382
        File tmpDir = getTempDirectory();
383
        MultipartRequest mr = null;
384
        Map<String, File> mmFileParts = null;
385
        File replicaFile = null;
386
        InputStream replicaStream = null;
387
388
        // Read the incoming data from its Mime Multipart encoding
389
        logMetacat.debug("Parsing Replica from the mime multipart entity");
390
391
        // handle MMP inputs
392
        MultipartRequestResolver mrr =
393
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
394
395
        try {
396
            mr = mrr.resolveMultipart(request);
397
            logMetacat.debug("Resolved the Replica multipart request.");
398
399
        } catch (IOException e) {
400
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
401
                e.getMessage());
402
403
        } catch (FileUploadException e) {
404
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
405
                    e.getMessage());
406
407
        } catch (Exception e) {
408
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
409
                    e.getMessage());
410
411
        }
412
413
        // get the map of file parts
414
        mmFileParts = mr.getMultipartFiles();
415
416
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
417
            throw new InvalidRequest("4853", "The multipart request must include " +
418
                "a file with the name 'replicaMetadata'.");
419
420
        }
421
422
        multipartparams = mr.getMultipartParameters();
423
        replicaFile = mmFileParts.get("replicaMetadata");
424
425
        if ( replicaFile == null ) {
426
            throw new InvalidRequest("4853", "The multipart request must include " +
427
            "a file with the name 'replicaMetadata'.");
428
429
        }
430
431
432
        // deserialize the ReplicationPolicy
433
        try {
434
            replicaStream = new FileInputStream(replicaFile);
435
        } catch (FileNotFoundException e) {
436
            throw new ServiceFailure("4852", "Couldn't find the multipart file: " +
437
                    e.getMessage());
438
439
        }
440
441
        try {
442
            replica = TypeMarshaller.unmarshalTypeFromStream(Replica.class, replicaStream);
443
        } catch (IOException e) {
444
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
445
                    e.getMessage());
446
447
        } catch (InstantiationException e) {
448
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
449
                    e.getMessage());
450
451
        } catch (IllegalAccessException e) {
452
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
453
                    e.getMessage());
454
455
        } catch (JiBXException e) {
456
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
457
                    e.getMessage());
458
459
        }
460
461
        return replica;
462
463
    }
464 6514 leinfelder
465 6590 cjones
    protected AccessPolicy collectAccessPolicy()
466
        throws IOException, ServiceFailure, InvalidRequest, JiBXException,
467
        InstantiationException, IllegalAccessException, ParserConfigurationException,
468
        SAXException  {
469 6514 leinfelder
470
		// Read the incoming data from its Mime Multipart encoding
471
		logMetacat.debug("Disassembling MIME multipart form");
472
		InputStream ap = null;
473
474
		// handle MMP inputs
475
		File tmpDir = getTempDirectory();
476
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
477
		MultipartRequestResolver mrr =
478
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
479
		MultipartRequest mr = null;
480
		try {
481
			mr = mrr.resolveMultipart(request);
482
		} catch (Exception e) {
483
			throw new ServiceFailure("2161",
484
					"Could not resolve multipart: " + e.getMessage());
485
		}
486
		logMetacat.debug("resolved multipart request");
487
		Map<String, File> files = mr.getMultipartFiles();
488
		if (files == null || files.keySet() == null) {
489
			throw new InvalidRequest("2163",
490
					"must have multipart file with name 'accessPolicy'");
491
		}
492
		logMetacat.debug("got multipart files");
493
494
		multipartparams = mr.getMultipartParameters();
495
496
		File apFile = files.get("accessPolicy");
497
		if (apFile == null) {
498
			throw new InvalidRequest("2163",
499
					"Missing the required file-part 'accessPolicy' from the multipart request.");
500
		}
501
		logMetacat.debug("apFile: " + apFile.getAbsolutePath());
502
		ap = new FileInputStream(apFile);
503
504
		AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromStream(AccessPolicy.class, ap);
505
		return accessPolicy;
506
	}
507
508 6590 cjones
    protected SystemMetadata collectSystemMetadata()
509
        throws IOException, FileUploadException, ServiceFailure, InvalidRequest,
510
        JiBXException, InstantiationException, IllegalAccessException  {
511 6269 leinfelder
512
		// Read the incoming data from its Mime Multipart encoding
513
		logMetacat.debug("Disassembling MIME multipart form");
514
		InputStream sysmeta = null;
515
516
		// handle MMP inputs
517
		File tmpDir = getTempDirectory();
518
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
519
		MultipartRequestResolver mrr =
520
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
521
		MultipartRequest mr = null;
522
		try {
523
			mr = mrr.resolveMultipart(request);
524 7266 cjones
525 6269 leinfelder
		} catch (Exception e) {
526 7266 cjones
		  if ( logMetacat.isDebugEnabled() ) {
527
		      e.printStackTrace();
528
529
		  }
530 6269 leinfelder
			throw new ServiceFailure("1202",
531
					"Could not resolve multipart: " + e.getMessage());
532 7266 cjones
533 6269 leinfelder
		}
534
		logMetacat.debug("resolved multipart request");
535
		Map<String, File> files = mr.getMultipartFiles();
536
		if (files == null) {
537
			throw new ServiceFailure("1202",
538
					"register meta must have multipart file with name 'sysmeta'");
539
		}
540
		logMetacat.debug("got multipart files");
541
542
		if (files.keySet() == null) {
543
			logMetacat.error("No file keys in MMP request.");
544
			throw new ServiceFailure(
545
					"1202",
546
					"No file keys found in MMP.  "
547
							+ "register meta must have multipart file with name 'sysmeta'");
548
		}
549
550
		// for logging purposes, dump out the key-value pairs that
551
		// constitute the request
552
		// 3 types exist: request params, multipart params, and
553
		// multipart files
554
		Iterator it = files.keySet().iterator();
555
		logMetacat.debug("iterating through request parts: " + it);
556
		while (it.hasNext()) {
557
			String key = (String) it.next();
558
			logMetacat.debug("files key: " + key);
559
			logMetacat.debug("files value: " + files.get(key));
560
		}
561
562
		multipartparams = mr.getMultipartParameters();
563
		it = multipartparams.keySet().iterator();
564
		while (it.hasNext()) {
565
			String key = (String) it.next();
566
			logMetacat.debug("multipartparams key: " + key);
567
			logMetacat.debug("multipartparams value: " + multipartparams.get(key));
568
		}
569
570
		it = params.keySet().iterator();
571
		while (it.hasNext()) {
572
			String key = (String) it.next();
573
			logMetacat.debug("param key: " + key);
574
			logMetacat.debug("param value: " + params.get(key));
575
		}
576
		logMetacat.debug("done iterating the request...");
577
578
		File smFile = files.get("sysmeta");
579
		if (smFile == null) {
580
			throw new InvalidRequest("1102",
581
					"Missing the required file-part 'sysmeta' from the multipart request.");
582
		}
583
		logMetacat.debug("smFile: " + smFile.getAbsolutePath());
584
		sysmeta = new FileInputStream(smFile);
585
586
		logMetacat.debug("Commence creation...");
587 6367 leinfelder
		SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
588 6269 leinfelder
		return systemMetadata;
589
	}
590
591 6972 leinfelder
    /**
592
     * Process the MMP request that includes files for each param
593 7092 cjones
     * @return map of param key and the temp file that contains the encoded information
594 6972 leinfelder
     * @throws ServiceFailure
595
     * @throws InvalidRequest
596
     */
597 6590 cjones
    protected Map<String, File> collectMultipartFiles()
598
        throws ServiceFailure, InvalidRequest {
599 6269 leinfelder
600
        // Read the incoming data from its Mime Multipart encoding
601
        logMetacat.debug("Disassembling MIME multipart form");
602
603
        // handle MMP inputs
604
        File tmpDir = getTempDirectory();
605 6272 leinfelder
        logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
606 6269 leinfelder
        MultipartRequestResolver mrr =
607
        	new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
608
        MultipartRequest mr = null;
609 7092 cjones
		    try {
610
		    	  mr = mrr.resolveMultipart(request);
611
612
		    } catch (Exception e) {
613
                throw new ServiceFailure("1202",
614
                		"Could not resolve multipart files: " + e.getMessage());
615
		    }
616 6272 leinfelder
        logMetacat.debug("resolved multipart request");
617 6269 leinfelder
        Map<String, File> files = mr.getMultipartFiles();
618
        if (files == null) {
619 6972 leinfelder
            throw new ServiceFailure("1202", "no multipart files found");
620 6269 leinfelder
        }
621 6272 leinfelder
        logMetacat.debug("got multipart files");
622 6269 leinfelder
623
        if (files.keySet() == null) {
624 6272 leinfelder
            logMetacat.error("No file keys in MMP request.");
625 6972 leinfelder
            throw new ServiceFailure("1202", "No file keys found in MMP.");
626 6269 leinfelder
        }
627 6995 leinfelder
628
        multipartparams = mr.getMultipartParameters();
629 6269 leinfelder
630 7092 cjones
		    // for logging purposes, dump out the key-value pairs that constitute the request
631
		    // 3 types exist: request params, multipart params, and multipart files
632 6972 leinfelder
        if (logMetacat.isDebugEnabled()) {
633
	        Iterator<String> it = files.keySet().iterator();
634
	        logMetacat.debug("iterating through files");
635
	        while (it.hasNext()) {
636
	            String key = it.next();
637
	            logMetacat.debug("files key: " + key);
638
	            logMetacat.debug("files value: " + files.get(key));
639
	        }
640
641
	        it = multipartparams.keySet().iterator();
642
	        logMetacat.debug("iterating through multipartparams");
643
	        while (it.hasNext()) {
644
	            String key = (String)it.next();
645
	            logMetacat.debug("multipartparams key: " + key);
646
	            logMetacat.debug("multipartparams value: " + multipartparams.get(key));
647
	        }
648
649
	        it = params.keySet().iterator();
650
	        logMetacat.debug("iterating through params");
651
	        while (it.hasNext()) {
652
	            String key = (String)it.next();
653
	            logMetacat.debug("param key: " + key);
654
	            logMetacat.debug("param value: " + params.get(key));
655
	        }
656
	        logMetacat.debug("done iterating the request...");
657 6269 leinfelder
        }
658
659
        return files;
660
    }
661
662 6140 cjones
		/**
663 6590 cjones
     *  copies request parameters to a hashtable which is given as argument to
664
     *  native metacathandler functions
665 5374 berkley
     */
666 6247 leinfelder
    protected void initParams() {
667 5211 jones
668 5374 berkley
        String name = null;
669
        String[] value = null;
670
        Enumeration paramlist = request.getParameterNames();
671
        while (paramlist.hasMoreElements()) {
672
            name = (String) paramlist.nextElement();
673
            value = request.getParameterValues(name);
674
            params.put(name, value);
675
        }
676
    }
677 6660 leinfelder
678
    /**
679
     * Collect the multipart params from the request
680
     * @throws Exception
681
     */
682
	protected void initMultipartParams() throws Exception {
683
684
		// Read the incoming data from its Mime Multipart encoding
685
		logMetacat.debug("Disassembling MIME multipart form");
686
687
		// handle MMP inputs
688
		File tmpDir = getTempDirectory();
689
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
690
		MultipartRequestResolver mrr =
691
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
692
		MultipartRequest mr = mrr.resolveMultipart(request);
693
694
		multipartparams = mr.getMultipartParameters();
695
	}
696 6469 leinfelder
697 5211 jones
    /**
698 5808 berkley
     * locate the boundary marker for an MMP
699 5462 berkley
     * @param is
700
     * @return
701 5808 berkley
     * @throws IOException
702 5462 berkley
     */
703 5639 berkley
    protected static String[] findBoundaryString(InputStream is)
704 6268 leinfelder
        throws IOException {
705 5639 berkley
        String[] endResult = new String[2];
706 5637 berkley
        String boundary = "";
707 5639 berkley
        String searchString = "boundary=";
708 5637 berkley
        byte[] b = new byte[1024];
709 5639 berkley
        int numbytes = is.read(b, 0, 1024);
710 5826 berkley
711 5639 berkley
        while(numbytes != -1)
712 5636 berkley
        {
713 5639 berkley
            String s = new String(b, 0, numbytes);
714 5826 berkley
            int searchStringIndex = s.indexOf(searchString);
715 5639 berkley
716
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
717
            { //the end of the boundary is in the next byte array
718
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
719
            }
720
            else if(!boundary.startsWith("--"))
721
            { //we can read the whole boundary from this byte array
722
                boundary = s.substring(searchStringIndex + searchString.length() + 1,
723
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
724
                boundary = "--" + boundary;
725
                endResult[0] = boundary;
726
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
727
                        s.length());
728
                break;
729
            }
730
            else
731
            { //we're now reading the 2nd byte array to get the rest of the boundary
732
                searchString = "\"";
733
                searchStringIndex = s.indexOf(searchString);
734
                boundary += s.substring(0, searchStringIndex);
735
                boundary = "--" + boundary;
736
                endResult[0] = boundary;
737
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
738
                        s.length());
739
                break;
740
            }
741 5637 berkley
        }
742 5639 berkley
        return endResult;
743
    }
744
745 5808 berkley
    /**
746 5838 berkley
     * return the directory where temp files are stored
747
     * @return
748
     */
749 6248 leinfelder
    protected static File getTempDirectory()
750 5838 berkley
    {
751
        File tmpDir = null;
752 6267 leinfelder
        Logger logMetacat = Logger.getLogger(D1ResourceHandler.class);
753 6268 leinfelder
        try {
754 5639 berkley
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
755
        }
756 6268 leinfelder
        catch(PropertyNotFoundException pnfe) {
757 6267 leinfelder
            logMetacat.error("D1ResourceHandler.writeMMPPartstoFiles: " +
758 5639 berkley
                    "application.tmpDir not found.  Using /tmp instead.");
759
            tmpDir = new File("/tmp");
760
        }
761 5838 berkley
        return tmpDir;
762 5639 berkley
    }
763
764 5637 berkley
    /**
765 5211 jones
     * Prints xml response
766
     * @param message Message to be displayed
767
     * @param response Servlet response that xml message will be printed
768
     * */
769 6247 leinfelder
    protected void printError(String message, HttpServletResponse response) {
770 5211 jones
        try {
771 6267 leinfelder
            logMetacat.error("D1ResourceHandler: Printing error to servlet response: " + message);
772 5211 jones
            PrintWriter out = response.getWriter();
773
            response.setContentType("text/xml");
774
            out.println("<?xml version=\"1.0\"?>");
775
            out.println("<error>");
776
            out.println(message);
777
            out.println("</error>");
778
            out.close();
779
        } catch (IOException e) {
780
            e.printStackTrace();
781
        }
782
    }
783 5370 berkley
784 5692 berkley
    /**
785
     * serialize a D1 exception using jibx
786
     * @param e
787
     * @param out
788
     */
789 6247 leinfelder
    protected void serializeException(BaseException e, OutputStream out) {
790 5319 jones
        // TODO: Use content negotiation to determine which return format to use
791
        response.setContentType("text/xml");
792
        response.setStatus(e.getCode());
793 5512 berkley
794 6267 leinfelder
        logMetacat.error("D1ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
795 5512 berkley
        e.printStackTrace();
796
797 5319 jones
        try {
798
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
799
        } catch (IOException e1) {
800
            logMetacat.error("Error writing exception to stream. "
801
                    + e1.getMessage());
802
        }
803
    }
804
805 5211 jones
}