Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2011 Regents of the University of California and the
4
 *              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
import java.io.File;
26
import java.io.FileInputStream;
27
import java.io.FileNotFoundException;
28
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
import java.util.Iterator;
35
import java.util.List;
36
import java.util.Map;
37
import java.util.Timer;
38

    
39
import javax.servlet.ServletContext;
40
import javax.servlet.http.HttpServletRequest;
41
import javax.servlet.http.HttpServletResponse;
42
import javax.xml.parsers.ParserConfigurationException;
43

    
44
import org.apache.commons.fileupload.FileUploadException;
45
import org.apache.commons.io.IOUtils;
46
import org.apache.log4j.Logger;
47
import org.dataone.client.auth.CertificateManager;
48
import org.dataone.mimemultipart.MultipartRequest;
49
import org.dataone.mimemultipart.MultipartRequestResolver;
50
import org.dataone.service.exceptions.BaseException;
51
import org.dataone.service.exceptions.InvalidRequest;
52
import org.dataone.service.exceptions.ServiceFailure;
53
import org.dataone.service.types.v1.AccessPolicy;
54
import org.dataone.service.types.v1.Replica;
55
import org.dataone.service.types.v1.ReplicationPolicy;
56
import org.dataone.service.types.v1.Session;
57
import org.dataone.service.types.v1.SystemMetadata;
58
import org.dataone.service.util.TypeMarshaller;
59
import org.jibx.runtime.JiBXException;
60
import org.xml.sax.SAXException;
61

    
62
import edu.ucsb.nceas.metacat.MetacatHandler;
63
import edu.ucsb.nceas.metacat.properties.PropertyService;
64
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
65
/**
66
 * 
67
 * Base class for handling D1 REST calls in Metacat
68
 * 
69
 * @author leinfelder
70
 */
71
public class D1ResourceHandler {
72

    
73
    /**HTTP Verb GET*/
74
    public static final byte GET = 1;
75
    /**HTTP Verb POST*/
76
    public static final byte POST = 2;
77
    /**HTTP Verb PUT*/
78
    public static final byte PUT = 3;
79
    /**HTTP Verb DELETE*/
80
    public static final byte DELETE = 4;
81
    /**HTTP Verb HEAD*/
82
    public static final byte HEAD = 5;
83

    
84
    /*
85
     * API Resources
86
     */
87
    protected static final String RESOURCE_BASE_URL = "d1";
88

    
89
    protected static final String RESOURCE_OBJECTS = "object";
90
    protected static final String RESOURCE_META = "meta";
91
    protected static final String RESOURCE_LOG = "log";
92
    protected static final String RESOURCE_CHECKSUM = "checksum";
93
    
94
    protected static final String RESOURCE_IS_AUTHORIZED = "isAuthorized";
95
    protected static final String RESOURCE_ACCESS_RULES = "accessRules";
96

    
97
    
98
    /*
99
     * API Functions used as URL parameters
100
     */
101
    protected static final String FUNCTION_NAME_INSERT = "insert";
102
    protected static final String FUNCTION_NAME_UPDATE = "update";
103
    
104
    protected ServletContext servletContext;
105
    protected Logger logMetacat;
106
    protected MetacatHandler handler;
107
    protected HttpServletRequest request;
108
    protected HttpServletResponse response;
109

    
110
    protected Hashtable<String, String[]> params;
111
    protected Map<String, List<String>> multipartparams;
112
    
113
    // D1 certificate-based authentication
114
    protected Session session;
115

    
116
    /**Initializes new instance by setting servlet context,request and response*/
117
    public D1ResourceHandler(ServletContext servletContext,
118
            HttpServletRequest request, HttpServletResponse response) {
119
        this.servletContext = servletContext;
120
        this.request = request;
121
        this.response = response;
122
    }
123

    
124
    /**
125
     * This function is called from REST API servlet and handles each request 
126
     * 
127
     * @param httpVerb (GET, POST, PUT or DELETE)
128
     */
129
    public void handle(byte httpVerb) {
130
        logMetacat = Logger.getLogger(D1ResourceHandler.class);
131
        try {
132
  
133
            // load session from certificate in request
134
            session = CertificateManager.getInstance().getSession(request);
135

    
136
            // initialize the parameters
137
            params = new Hashtable<String, String[]>();
138
            initParams();
139

    
140
            // create the handler for interacting with Metacat
141
            Timer timer = new Timer();
142
            handler = new MetacatHandler(timer);
143

    
144
        } catch (Exception e) {
145
        	// TODO: more D1 structure when failing here
146
        	response.setStatus(400);
147
            printError("Incorrect resource!", response);
148
            logMetacat.error(e.getClass() + ": " + e.getMessage(), e);
149
        }
150
    }
151
    
152
    protected String parseTrailing(String resource, String token) {
153
    	// get the rest
154
        String extra = null;
155
        if (resource.indexOf(token) != -1) {
156
        	// what comes after the token?
157
            extra = resource.substring(resource.indexOf(token) + token.length());
158
            // remove the slash
159
            if (extra.startsWith("/")) {
160
            	extra = extra.substring(1);
161
            }
162
            // is there anything left?
163
            if (extra.length() == 0) {
164
            	extra = null;
165
            }
166
        }
167
        return extra;
168
    }
169

    
170
    /**
171
     * Parse the replication policy document out of the mime-multipart form data
172
     * 
173
     * @return policy  the encoded policy
174
     * @throws ServiceFailure
175
     * @throws InvalidRequest
176
     * @throws IOException
177
     * @throws InstantiationException
178
     * @throws IllegalAccessException
179
     * @throws JiBXException
180
     */
181
    protected ReplicationPolicy collectReplicationPolicy() 
182
        throws ServiceFailure, InvalidRequest, IOException, InstantiationException, 
183
        IllegalAccessException, JiBXException {
184
        
185
        ReplicationPolicy policy = null;
186
        File tmpDir = getTempDirectory();
187
        MultipartRequest mr = null;
188
        Map<String, File> mmFileParts = null;
189
        File replPolicyFile = null;
190
        InputStream replPolicyStream = null;
191
        
192
        // Read the incoming data from its Mime Multipart encoding
193
        logMetacat.debug("Parsing ReplicationPolicy from the mime multipart entity");
194

    
195
        // handle MMP inputs
196
        MultipartRequestResolver mrr = 
197
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
198
        
199
        try {
200
            mr = mrr.resolveMultipart(request);
201
            logMetacat.debug("Resolved the ReplicationPolicy multipart request.");
202
            
203
        } catch (IOException e) {
204
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
205
                e.getMessage());
206
            
207
        } catch (FileUploadException e) {
208
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
209
                    e.getMessage());
210
            
211
        } catch (Exception e) {
212
            throw new ServiceFailure("4882", "Couldn't resolve the multipart request: " +
213
                    e.getMessage());
214
            
215
        }
216
        
217
        // get the map of file parts
218
        mmFileParts = mr.getMultipartFiles();
219
        
220
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
221
            throw new InvalidRequest("4883", "The multipart request must include " +
222
                "a file with the name 'policy'.");
223
            
224
        }
225
        
226
        multipartparams = mr.getMultipartParameters();
227
        replPolicyFile = mmFileParts.get("policy");
228
        
229
        if ( replPolicyFile == null ) {
230
            throw new InvalidRequest("4883", "The multipart request must include " +
231
            "a file with the name 'policy'.");
232
            
233
        }
234
        
235
        
236
        // deserialize the ReplicationPolicy
237
        replPolicyStream = new FileInputStream(replPolicyFile);
238
        policy = TypeMarshaller.unmarshalTypeFromStream(ReplicationPolicy.class, replPolicyStream);
239
        
240
        return policy;
241
        
242
    }
243

    
244
    /**
245
     * Parse the replica metadata document out of the mime-multipart form data
246
     * 
247
     * @return replica  the encoded replica
248
     * @throws ServiceFailure
249
     * @throws InvalidRequest
250
     * @throws IOException
251
     * @throws InstantiationException
252
     * @throws IllegalAccessException
253
     * @throws JiBXException
254
     */
255
    protected Replica collectReplicaMetadata() 
256
        throws ServiceFailure, InvalidRequest {
257
        
258
        Replica replica = null;
259
        File tmpDir = getTempDirectory();
260
        MultipartRequest mr = null;
261
        Map<String, File> mmFileParts = null;
262
        File replicaFile = null;
263
        InputStream replicaStream = null;
264
        
265
        // Read the incoming data from its Mime Multipart encoding
266
        logMetacat.debug("Parsing Replica from the mime multipart entity");
267

    
268
        // handle MMP inputs
269
        MultipartRequestResolver mrr = 
270
            new MultipartRequestResolver(tmpDir.getAbsolutePath(),1000000000, 0);
271
        
272
        try {
273
            mr = mrr.resolveMultipart(request);
274
            logMetacat.debug("Resolved the Replica multipart request.");
275
            
276
        } catch (IOException e) {
277
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
278
                e.getMessage());
279
            
280
        } catch (FileUploadException e) {
281
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
282
                    e.getMessage());
283
            
284
        } catch (Exception e) {
285
            throw new ServiceFailure("4852", "Couldn't resolve the multipart request: " +
286
                    e.getMessage());
287
            
288
        }
289
        
290
        // get the map of file parts
291
        mmFileParts = mr.getMultipartFiles();
292
        
293
        if ( mmFileParts == null || mmFileParts.keySet() == null) {
294
            throw new InvalidRequest("4853", "The multipart request must include " +
295
                "a file with the name 'replicaMetadata'.");
296
            
297
        }
298
        
299
        multipartparams = mr.getMultipartParameters();
300
        replicaFile = mmFileParts.get("replicaMetadata");
301
        
302
        if ( replicaFile == null ) {
303
            throw new InvalidRequest("4853", "The multipart request must include " +
304
            "a file with the name 'replicaMetadata'.");
305
            
306
        }
307
        
308
        
309
        // deserialize the ReplicationPolicy
310
        try {
311
            replicaStream = new FileInputStream(replicaFile);
312
        } catch (FileNotFoundException e) {
313
            throw new ServiceFailure("4852", "Couldn't find the multipart file: " +
314
                    e.getMessage());
315
            
316
        }
317
        
318
        try {
319
            replica = TypeMarshaller.unmarshalTypeFromStream(Replica.class, replicaStream);
320
        } catch (IOException e) {
321
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
322
                    e.getMessage());
323
            
324
        } catch (InstantiationException e) {
325
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
326
                    e.getMessage());
327
            
328
        } catch (IllegalAccessException e) {
329
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
330
                    e.getMessage());
331
            
332
        } catch (JiBXException e) {
333
            throw new ServiceFailure("4852", "Couldn't deserialize the replica document: " +
334
                    e.getMessage());
335
            
336
        }
337
        
338
        return replica;
339
        
340
    }
341
    
342
    protected AccessPolicy collectAccessPolicy() 
343
        throws IOException, ServiceFailure, InvalidRequest, JiBXException, 
344
        InstantiationException, IllegalAccessException, ParserConfigurationException, 
345
        SAXException  {
346
		
347
		// Read the incoming data from its Mime Multipart encoding
348
		logMetacat.debug("Disassembling MIME multipart form");
349
		InputStream ap = null;
350

    
351
		// handle MMP inputs
352
		File tmpDir = getTempDirectory();
353
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
354
		MultipartRequestResolver mrr = 
355
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
356
		MultipartRequest mr = null;
357
		try {
358
			mr = mrr.resolveMultipart(request);
359
		} catch (Exception e) {
360
			throw new ServiceFailure("2161", 
361
					"Could not resolve multipart: " + e.getMessage());
362
		}
363
		logMetacat.debug("resolved multipart request");
364
		Map<String, File> files = mr.getMultipartFiles();
365
		if (files == null || files.keySet() == null) {
366
			throw new InvalidRequest("2163",
367
					"must have multipart file with name 'accessPolicy'");
368
		}
369
		logMetacat.debug("got multipart files");
370

    
371
		multipartparams = mr.getMultipartParameters();
372

    
373
		File apFile = files.get("accessPolicy");
374
		if (apFile == null) {
375
			throw new InvalidRequest("2163",
376
					"Missing the required file-part 'accessPolicy' from the multipart request.");
377
		}
378
		logMetacat.debug("apFile: " + apFile.getAbsolutePath());
379
		ap = new FileInputStream(apFile);
380
	
381
		AccessPolicy accessPolicy = TypeMarshaller.unmarshalTypeFromStream(AccessPolicy.class, ap);
382
		return accessPolicy;
383
	}
384
    
385
    protected SystemMetadata collectSystemMetadata() 
386
        throws IOException, FileUploadException, ServiceFailure, InvalidRequest, 
387
        JiBXException, InstantiationException, IllegalAccessException  {
388
		
389
		// Read the incoming data from its Mime Multipart encoding
390
		logMetacat.debug("Disassembling MIME multipart form");
391
		InputStream sysmeta = null;
392

    
393
		// handle MMP inputs
394
		File tmpDir = getTempDirectory();
395
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
396
		MultipartRequestResolver mrr = 
397
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
398
		MultipartRequest mr = null;
399
		try {
400
			mr = mrr.resolveMultipart(request);
401
		} catch (Exception e) {
402
			throw new ServiceFailure("1202", 
403
					"Could not resolve multipart: " + e.getMessage());
404
		}
405
		logMetacat.debug("resolved multipart request");
406
		Map<String, File> files = mr.getMultipartFiles();
407
		if (files == null) {
408
			throw new ServiceFailure("1202",
409
					"register meta must have multipart file with name 'sysmeta'");
410
		}
411
		logMetacat.debug("got multipart files");
412

    
413
		if (files.keySet() == null) {
414
			logMetacat.error("No file keys in MMP request.");
415
			throw new ServiceFailure(
416
					"1202",
417
					"No file keys found in MMP.  "
418
							+ "register meta must have multipart file with name 'sysmeta'");
419
		}
420

    
421
		// for logging purposes, dump out the key-value pairs that
422
		// constitute the request
423
		// 3 types exist: request params, multipart params, and
424
		// multipart files
425
		Iterator it = files.keySet().iterator();
426
		logMetacat.debug("iterating through request parts: " + it);
427
		while (it.hasNext()) {
428
			String key = (String) it.next();
429
			logMetacat.debug("files key: " + key);
430
			logMetacat.debug("files value: " + files.get(key));
431
		}
432

    
433
		multipartparams = mr.getMultipartParameters();
434
		it = multipartparams.keySet().iterator();
435
		while (it.hasNext()) {
436
			String key = (String) it.next();
437
			logMetacat.debug("multipartparams key: " + key);
438
			logMetacat.debug("multipartparams value: " + multipartparams.get(key));
439
		}
440

    
441
		it = params.keySet().iterator();
442
		while (it.hasNext()) {
443
			String key = (String) it.next();
444
			logMetacat.debug("param key: " + key);
445
			logMetacat.debug("param value: " + params.get(key));
446
		}
447
		logMetacat.debug("done iterating the request...");
448

    
449
		File smFile = files.get("sysmeta");
450
		if (smFile == null) {
451
			throw new InvalidRequest("1102",
452
					"Missing the required file-part 'sysmeta' from the multipart request.");
453
		}
454
		logMetacat.debug("smFile: " + smFile.getAbsolutePath());
455
		sysmeta = new FileInputStream(smFile);
456
	
457
		logMetacat.debug("Commence creation...");
458
		SystemMetadata systemMetadata = TypeMarshaller.unmarshalTypeFromStream(SystemMetadata.class, sysmeta);
459
		return systemMetadata;
460
	}
461
    
462
    protected Map<String, File> collectMultipartFiles() 
463
        throws ServiceFailure, InvalidRequest {
464
    	
465
        // Read the incoming data from its Mime Multipart encoding
466
        logMetacat.debug("Disassembling MIME multipart form");
467
        InputStream object = null;
468
        InputStream sysmeta = null;
469
        
470
        
471
        // handle MMP inputs
472
        File tmpDir = getTempDirectory();
473
        logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
474
        MultipartRequestResolver mrr = 
475
        	new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
476
        MultipartRequest mr = null;
477
		try {
478
			mr = mrr.resolveMultipart(request);
479
		} catch (Exception e) {
480
            throw new ServiceFailure("1202", 
481
            		"Could not resolve multipart files: " + e.getMessage());
482
		}
483
        logMetacat.debug("resolved multipart request");
484
        Map<String, File> files = mr.getMultipartFiles();
485
        if (files == null) {
486
            throw new ServiceFailure("1202", "create/update must have multipart files with names 'object' and 'sysmeta'");
487
        }
488
        logMetacat.debug("got multipart files");
489
        
490
        if (files.keySet() == null) {
491
            logMetacat.error("No file keys in MMP request.");
492
            throw new ServiceFailure("1202", "No file keys found in MMP.  " +
493
                    "create/update must have multipart files with names 'object' and 'sysmeta'");
494
        }
495

    
496
		// for logging purposes, dump out the key-value pairs that constitute the request
497
		// 3 types exist: request params, multipart params, and multipart files
498
        Iterator it = files.keySet().iterator();
499
        logMetacat.debug("iterating through files");
500
        while (it.hasNext()) {
501
            String key = (String)it.next();
502
            logMetacat.debug("files key: " + key);
503
            logMetacat.debug("files value: " + files.get(key));
504
        }
505
        
506
        multipartparams = mr.getMultipartParameters();
507
        it = multipartparams.keySet().iterator();
508
        logMetacat.debug("iterating through multipartparams");
509
        while (it.hasNext()) {
510
            String key = (String)it.next();
511
            logMetacat.debug("multipartparams key: " + key);
512
            logMetacat.debug("multipartparams value: " + multipartparams.get(key));
513
        }
514
        
515
        it = params.keySet().iterator();
516
        logMetacat.debug("iterating through params");
517
        while (it.hasNext()) {
518
            String key = (String)it.next();
519
            logMetacat.debug("param key: " + key);
520
            logMetacat.debug("param value: " + params.get(key));
521
        }
522
        logMetacat.debug("done iterating the request...");
523

    
524
        File smFile = files.get("sysmeta");
525
		if (smFile == null) {
526
		    throw new InvalidRequest("1102", "Missing the required file-part 'sysmeta' from the multipart request.");
527
		}
528
        logMetacat.debug("smFile: " + smFile.getAbsolutePath());
529
        File objFile = files.get("object");
530
		if (objFile == null) {
531
		    throw new InvalidRequest("1102", "Missing the required file-part 'object' from the multipart request.");
532
		}
533
        logMetacat.debug("objectfile: " + objFile.getAbsolutePath());
534
        
535
        return files;
536
    }
537
    
538
		/**
539
     *  copies request parameters to a hashtable which is given as argument to 
540
     *  native metacathandler functions  
541
     */
542
    protected void initParams() {
543

    
544
        String name = null;
545
        String[] value = null;
546
        Enumeration paramlist = request.getParameterNames();
547
        while (paramlist.hasMoreElements()) {
548
            name = (String) paramlist.nextElement();
549
            value = request.getParameterValues(name);
550
            params.put(name, value);
551
        }
552
    }
553
    
554
    /**
555
     * Collect the multipart params from the request
556
     * @throws Exception 
557
     */
558
	protected void initMultipartParams() throws Exception {
559
		
560
		// Read the incoming data from its Mime Multipart encoding
561
		logMetacat.debug("Disassembling MIME multipart form");
562
	
563
		// handle MMP inputs
564
		File tmpDir = getTempDirectory();
565
		logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
566
		MultipartRequestResolver mrr = 
567
			new MultipartRequestResolver(tmpDir.getAbsolutePath(), 1000000000, 0);
568
		MultipartRequest mr = mrr.resolveMultipart(request);
569
		
570
		multipartparams = mr.getMultipartParameters();
571
	}
572
   
573
    /**
574
     * locate the boundary marker for an MMP
575
     * @param is
576
     * @return
577
     * @throws IOException
578
     */
579
    protected static String[] findBoundaryString(InputStream is)
580
        throws IOException {
581
        String[] endResult = new String[2];
582
        String boundary = "";
583
        String searchString = "boundary=";
584
        byte[] b = new byte[1024];
585
        int numbytes = is.read(b, 0, 1024);
586

    
587
        while(numbytes != -1)
588
        {
589
            String s = new String(b, 0, numbytes);
590
            int searchStringIndex = s.indexOf(searchString);
591
            
592
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
593
            { //the end of the boundary is in the next byte array
594
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
595
            }
596
            else if(!boundary.startsWith("--"))
597
            { //we can read the whole boundary from this byte array
598
                boundary = s.substring(searchStringIndex + searchString.length() + 1, 
599
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
600
                boundary = "--" + boundary;
601
                endResult[0] = boundary;
602
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
603
                        s.length());
604
                break;
605
            }
606
            else
607
            { //we're now reading the 2nd byte array to get the rest of the boundary
608
                searchString = "\"";
609
                searchStringIndex = s.indexOf(searchString);
610
                boundary += s.substring(0, searchStringIndex);
611
                boundary = "--" + boundary;
612
                endResult[0] = boundary;
613
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
614
                        s.length());
615
                break;
616
            }
617
        }
618
        return endResult;
619
    }
620
    
621
    /**
622
     * return the directory where temp files are stored
623
     * @return
624
     */
625
    protected static File getTempDirectory()
626
    {
627
        File tmpDir = null;
628
        Logger logMetacat = Logger.getLogger(D1ResourceHandler.class);
629
        try {
630
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
631
        }
632
        catch(PropertyNotFoundException pnfe) {
633
            logMetacat.error("D1ResourceHandler.writeMMPPartstoFiles: " +
634
                    "application.tmpDir not found.  Using /tmp instead.");
635
            tmpDir = new File("/tmp");
636
        }
637
        return tmpDir;
638
    }
639
    
640
    /**
641
     * Prints xml response
642
     * @param message Message to be displayed
643
     * @param response Servlet response that xml message will be printed 
644
     * */
645
    protected void printError(String message, HttpServletResponse response) {
646
        try {
647
            logMetacat.error("D1ResourceHandler: Printing error to servlet response: " + message);
648
            PrintWriter out = response.getWriter();
649
            response.setContentType("text/xml");
650
            out.println("<?xml version=\"1.0\"?>");
651
            out.println("<error>");
652
            out.println(message);
653
            out.println("</error>");
654
            out.close();
655
        } catch (IOException e) {
656
            e.printStackTrace();
657
        }
658
    }
659
    
660
    /**
661
     * serialize a D1 exception using jibx
662
     * @param e
663
     * @param out
664
     */
665
    protected void serializeException(BaseException e, OutputStream out) {
666
        // TODO: Use content negotiation to determine which return format to use
667
        response.setContentType("text/xml");
668
        response.setStatus(e.getCode());
669
        
670
        logMetacat.error("D1ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
671
        e.printStackTrace();
672
        
673
        try {
674
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
675
        } catch (IOException e1) {
676
            logMetacat.error("Error writing exception to stream. " 
677
                    + e1.getMessage());
678
        }
679
    }
680

    
681
}
(4-4/9)