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.*;
26
import java.net.URL;
27
import java.util.*;
28

    
29
import javax.mail.BodyPart;
30
import javax.mail.MessagingException;
31
import javax.mail.internet.MimeMultipart;
32
import javax.servlet.ServletContext;
33
import javax.servlet.http.HttpServletRequest;
34
import javax.servlet.http.HttpServletResponse;
35

    
36
import java.security.NoSuchAlgorithmException;
37
import java.sql.SQLException;
38
import java.text.DateFormat;
39
import java.text.ParseException;
40
import java.text.ParsePosition;
41
import java.text.SimpleDateFormat;
42

    
43

    
44
import org.apache.commons.io.IOUtils;
45
import org.apache.log4j.Logger;
46
import org.apache.maven.artifact.ant.shaded.IOUtil;
47
import org.dataone.client.MNode;
48
import org.dataone.mimemultipart.MultipartRequest;
49
import org.dataone.mimemultipart.MultipartRequestResolver;
50
import org.dataone.service.NodeListParser;
51
import org.dataone.service.exceptions.BaseException;
52
import org.dataone.service.exceptions.IdentifierNotUnique;
53
import org.dataone.service.exceptions.InsufficientResources;
54
import org.dataone.service.exceptions.InvalidRequest;
55
import org.dataone.service.exceptions.InvalidSystemMetadata;
56
import org.dataone.service.exceptions.InvalidToken;
57
import org.dataone.service.exceptions.NotAuthorized;
58
import org.dataone.service.exceptions.NotImplemented;
59
import org.dataone.service.exceptions.ServiceFailure;
60
import org.dataone.service.exceptions.UnsupportedType;
61
import org.dataone.service.exceptions.NotFound;
62
import org.dataone.service.types.*;
63
import org.dataone.service.types.util.ServiceTypeUtil;
64
import org.jibx.runtime.BindingDirectory;
65
import org.jibx.runtime.IBindingFactory;
66
import org.jibx.runtime.IMarshallingContext;
67
import org.jibx.runtime.IUnmarshallingContext;
68
import org.jibx.runtime.JiBXException;
69

    
70
import edu.ucsb.nceas.metacat.AccessionNumberException;
71
import edu.ucsb.nceas.metacat.DBUtil;
72
import edu.ucsb.nceas.metacat.IdentifierManager;
73
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
74
import edu.ucsb.nceas.metacat.MetaCatServlet;
75
import edu.ucsb.nceas.metacat.MetacatHandler;
76
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
77
import edu.ucsb.nceas.metacat.dataone.CrudService;
78
import edu.ucsb.nceas.metacat.dataone.HealthService;
79
import edu.ucsb.nceas.metacat.properties.PropertyService;
80
import edu.ucsb.nceas.metacat.service.SessionService;
81
import edu.ucsb.nceas.metacat.util.RequestUtil;
82
import edu.ucsb.nceas.metacat.util.SystemUtil;
83
import edu.ucsb.nceas.metacat.util.SessionData;
84
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
85

    
86
import org.dataone.service.streaming.util.StreamUtil;
87

    
88
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
89
import com.oreilly.servlet.multipart.FilePart;
90
import com.oreilly.servlet.multipart.MultipartParser;
91
import com.oreilly.servlet.multipart.ParamPart;
92
import com.oreilly.servlet.multipart.Part;
93
/**
94
 * 
95
 * Implements Earthgrid REST API to Metacat <br/><br/> 
96
 * 
97
 * <ul>
98
 * <li>
99
 * <h3> EarthGrid Query Service</h3>
100
 * <ul><li>
101
 * <h3>Get & Authenticated Get:</h3> 
102
 * is equal to Metacat's read action and returns a data file having
103
 * the specified <doc-id> in the resource path. For authenticated Get service, a session id must be provided 
104
 * in the query string. <br/><br/>
105
 * 
106
 * <b>REST URL:</b> <code>GET, [context-root]/object/[doc-id]?sessionid=[sessionid] </code><br/>
107
 * <b>Returns:</b> data file <br/><br/>
108
 * </li>
109
 * 
110
 * <li>
111
 * <h3>Query & Authenticated Query:</h3> 
112
 * Metacat's equivalent is squery action but this function 
113
 * receives a Earthgrid query document and returns Earthgrid resultset document by transforming those documents
114
 * to Metacat's equivalents by the means of Metacat Implementation in Earthgrid library. For authenticated Query service 
115
 * a session id must be provided in the query string. See Earthgrid (a.k.a. Ecogrid) project for XSD files of 
116
 * query and resultset documents<br/><br/>
117
 * 
118
 * <b>REST URL:</b> <code>POST, [context-root]/object?sessionid=[sessionid]</code>    <br/>
119
 * <b>POST Data:</b> Earthgrid query document , Content-type: <code>text/xml</code><br/>
120
 * <b>Returns:</b> Earthgrid resultset document<br/><br/>
121
 * 
122
 * </li>
123
 * </ul>
124
 * 
125
 * </li>
126
 * 
127
 * <li>
128
 * <h3> EarthGrid Authentication Service</h3>
129
 * <ul><li>
130
 * <h3>Login: </h3> 
131
 * Receives username and password parameters in POST data and 
132
 * returns SessionId (in XML format) or failure message and uses MetacatHandler's handleLoginAction function<br/><br/>
133
 *  
134
 * <b>REST URL:</b> <code>POST, [context-root]/session?op=login</code> <br/>
135
 * <b>POST Data:</b> username=[username]&password=[password], Content-type: <code>application/x-www-form-urlencoded</code>
136
 * <b>Returns:</b> sessionId in XML format<br/><br/>
137
 * </li>
138
 * 
139
 * <li>
140
 * <h3>Logout: </h3> 
141
 * Receives session Id parameters in querystring and returns xml message, calls 
142
 * MetacatHandler's handleLogoutAction function<br/><br/>
143
 *  
144
 * <b>REST URL:</b> <code>GET, [context-root]/session?op=logout&sessionid=[sessionid]</code>   <br/>
145
 * <b>Returns:</b> message in XML format<br/><br/>
146
 * </li>
147
 * </ul>
148
 * 
149
 * <li>
150
 * <h3>EarthGrid Put Service</h3>
151
 * 
152
 * <ul>
153
 * <li><h3>Update/Insert: </h3>     
154
 * <br/>
155
 * <b>REST URL:</b> <code>PUT, [context-root]/object/[doc-id]?op={update|insert}&sessionid=[sessionid]</code>   <br/>
156
 * <b>POST Data:</b> document object, Content-type: <code>text/xml</code><br/>
157
 * <b>Returns:</b> message in XML format<br/><br/>
158
 * </li>
159
 * 
160
 * <li><h3>Delete: </h3>        
161
 * <br/>
162
 * <b>REST URL:</b> <code>DELETE, [context-root]/object/[doc-id]?sessionid=[sessionid]</code>   <br/>
163
 * <b>Returns:</b> message in XML format<br/><br/>
164
 * </li>
165

    
166
 * </ul>
167
 * </li>
168
 * 
169
 * <li>
170
 * <h3>EarthGrid Identifier Service</h3><br/>
171
 * 
172
 * <ul>
173
 * <li><h3>isRegistered: </h3>      <br/>
174
 * <b>REST URL:</b> <code>GET, [context-root]/identifier/[doc-id]?op=isregistered</code>   <br/>
175
 * <b>Returns:</b> message in XML format<br/><br/>
176
 * </li>
177

    
178
 * <li><h3>getAllDocIds:</h3>       <br/>       
179
 * <b>REST URL:</b> <code>GET, [context-root]/identifier?op=getalldocids</code>   <br/>
180
 * <b>Returns:</b> document id list in XML format<br/><br/>
181
 * </li>
182
 * 
183
 * <li><h3>addLSID Function:</h3> 
184
 * Metacat does not support this function       <br/>
185
 * <b>REST URL:</b> <code>PUT, [context-root]/identifier/[doc-id]</code>   <br/>
186
 * <b>Returns:</b> error message in XML format<br/><br/>
187
 * </li>
188
 * 
189
 * <li><h3>getNextRevision:</h3>        <br/>
190
 * <b>REST URL:</b> <code>GET, [context-root]/identifier/[doc-id]?op=getnextrevision</code>   <br/>
191
 * <b>Returns:</b> message in XML format<br/><br/>
192
 * </li>
193
 * 
194
 * <li><h3>getNextObject:</h3>      <br/>
195
 * <b>REST URL:</b> <code>GET, [context-root]/identifier?op=getnextobject&scope=[scope]</code>   <br/>
196
 * <b>Returns:</b> message in XML format<br/><br/>
197
 * </li>
198
 * 
199
 * </li>
200
 * </ul>
201
 * 
202
 */
203
public class ResourceHandler {
204

    
205
    /**HTTP Verb GET*/
206
    public static final byte GET = 1;
207
    /**HTTP Verb POST*/
208
    public static final byte POST = 2;
209
    /**HTTP Verb PUT*/
210
    public static final byte PUT = 3;
211
    /**HTTP Verb DELETE*/
212
    public static final byte DELETE = 4;
213
    /**HTTP Verb HEAD*/
214
    public static final byte HEAD = 5;
215

    
216
    /*
217
     * API Resources
218
     */
219
    private static final String RESOURCE_OBJECTS = "object";
220
    private static final String RESOURCE_META = "meta";
221
    private static final String RESOURCE_SESSION = "session";
222
    private static final String RESOURCE_IDENTIFIER = "identifier";
223
    private static final String RESOURCE_LOG = "log";
224
    private static final String RESOURCE_CHECKSUM = "checksum";
225
    private static final String RESOURCE_MONITOR = "monitor";
226
    private static final String RESOURCE_BASE_URL = "d1";
227
    private static final String RESOURCE_REPLICATE = "replicate";
228

    
229
    /*
230
     * API Functions used as URL parameters
231
     */
232
    private static final String FUNCTION_KEYWORD = "op";
233
    private static final String FUNCTION_NAME_LOGIN = "login";
234
    private static final String FUNCTION_NAME_LOGOUT = "logout";
235
    private static final String FUNCTION_NAME_SET_ACCESS = "setaccess";
236
    private static final String FUNCTION_NAME_ISREGISTERED = "isregistered";
237
    private static final String FUNCTION_NAME_GETALLDOCS = "getalldocids";
238
    private static final String FUNCTION_NAME_GETNEXTREV = "getnextrevision";
239
    private static final String FUNCTION_NAME_GETNEXTOBJ = "getnextobject";
240
    private static final String FUNCTION_NAME_INSERT = "insert";
241
    private static final String FUNCTION_NAME_UPDATE = "update";
242
    private static final String FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA = "generatemissingsystemmetadata";
243

    
244
    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
245
    
246
    private ServletContext servletContext;
247
    private Logger logMetacat;
248
    private MetacatHandler handler;
249
    private HttpServletRequest request;
250
    private HttpServletResponse response;
251
    private String username;
252
    private String password;
253
    private String sessionId;
254
    private String[] groupNames;
255

    
256
    private Hashtable<String, String[]> params;
257

    
258
    /**Initializes new instance by setting servlet context,request and response*/
259
    public ResourceHandler(ServletContext servletContext,
260
            HttpServletRequest request, HttpServletResponse response) {
261
        this.servletContext = servletContext;
262
        this.request = request;
263
        this.response = response;
264
    }
265

    
266
    /**
267
     * This function is called from REST APU servlet and handles each request to the servlet 
268
     * 
269
     * @param httpVerb (GET, POST, PUT or DELETE)
270
     */
271
    public void handle(byte httpVerb) {
272
        logMetacat = Logger.getLogger(ResourceHandler.class);
273
        try {
274
            String resource = request.getServletPath();
275
            if(resource.endsWith("d1/") || resource.endsWith("d1"))
276
            {
277
                resource = RESOURCE_BASE_URL;
278
            }
279
            else
280
            {
281
                //substring off the /d1/
282
                resource = resource.substring(resource.indexOf("d1/") + 3, resource.length());
283
                resource = resource.trim();
284
            }
285
            
286
            String verb = "";
287
            
288
            System.out.println("handling verb " + httpVerb + " request with resource '" + resource + "'");
289
            System.out.println("resource: '" + resource + "'");
290
            System.out.println("resource_monitor: '" + RESOURCE_MONITOR + "'");
291
            boolean status = false;
292
            loadSessionData();
293

    
294
            if (resource != null) {
295
                //resource = request.getServletPath().substring(1);
296

    
297
                params = new Hashtable<String, String[]>();
298
                initParams();
299

    
300
                Timer timer = new Timer();
301
                handler = new MetacatHandler(timer);
302

    
303
                if(resource.equals(RESOURCE_BASE_URL)) {
304
                    //node registry response
305
                    System.out.println("Using resource 'd1' (node registry response)");
306
                    createNodeResponse();
307
                    status = true;
308
                    
309
                } else if (resource.equals(RESOURCE_SESSION) && 
310
                        httpVerb == POST && 
311
                        params.get(FUNCTION_KEYWORD) != null) {
312
                    System.out.println("Using resource 'session'");
313
                    //System.out.println("function_keyword: " + params.get(FUNCTION_KEYWORD)[0]);
314
                    if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGIN)) {
315
                        login();
316
                        status = true;
317
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGOUT)) {
318
                        logout();
319
                        status = true;
320
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_SET_ACCESS)) {
321
                        setaccess();
322
                        status = true;
323
                        System.out.println("done setting access");
324
                    }
325
                } else if (resource.equals(RESOURCE_META)) {
326
                    System.out.println("Using resource 'meta'");
327
                    if(params != null && params.get(FUNCTION_KEYWORD) != null &&
328
                            params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA))
329
                    { //generate system metadata for any object that is
330
                        //a) not system metadata itself
331
                        //b) does not already have a system metadata id in the systemmetadata table
332
                        //c) not a BIN object (data)
333
                        //TODO: check if we need this anymore.  Might be superceded
334
                        //by MetacatPopulator
335
                        generateMissingSystemMetadata();
336
                        status = true;
337
                    }
338
                    else
339
                    {
340
                        String objectId = request.getPathInfo();
341
                        if (objectId != null && objectId.length() > 1) 
342
                        {
343
                            objectId = request.getPathInfo().substring(1);
344
                        }
345
                        getSystemMetadataObject(objectId);
346
                        status = true;
347
                    }
348

    
349
                } else if (resource.equals(RESOURCE_OBJECTS)) {
350
                    System.out.println("Using resource 'object'");
351
                    logMetacat.debug("D1 Rest: Starting resource processing...");
352
                    loadSessionData();
353

    
354
                    String objectId = request.getPathInfo();
355
                    if (objectId != null && objectId.length() > 1) 
356
                    {
357
                        objectId = request.getPathInfo().substring(1);
358
                    }
359
                    else
360
                    {
361
                        objectId = null;
362
                    }
363
                    
364
                    System.out.println("objectId in ReasourceHandler.handle: " + objectId);
365

    
366
                    logMetacat.debug("verb:" + httpVerb);
367

    
368
                    if (httpVerb == GET) {
369
                        getObject(objectId);
370
                        status = true;
371
                    } else if (httpVerb == POST) {
372
                        putObject(objectId, FUNCTION_NAME_INSERT);
373
                        status = true;
374
                    } else if (httpVerb == PUT) {
375
                        putObject(objectId, FUNCTION_NAME_UPDATE);
376
                        status = true;
377
                    } else if (httpVerb == DELETE) {
378
                        deleteObject(objectId);
379
                        status = true;
380
                    } else if (httpVerb == HEAD) {
381
                        describeObject(objectId);
382
                        status = true;
383
                    }
384
                    
385

    
386
                } else if (resource.equals(RESOURCE_IDENTIFIER)) {
387
                    System.out.println("Using resource 'identifier'");
388
                    String identifierId = request.getPathInfo();
389
                    if (identifierId != null && identifierId.length() > 1)
390
                        identifierId = request.getPathInfo().substring(1); //trim the slash
391

    
392
                    if (httpVerb == GET) {
393
                        String op = params.get(FUNCTION_KEYWORD)[0];
394
                        if (op.equals(FUNCTION_NAME_ISREGISTERED)) {
395
                            isRegistered(identifierId);
396
                            status = true;
397
                        } else if (op.equals(FUNCTION_NAME_GETALLDOCS)) {
398
                            getAllDocIds();
399
                            status = true;
400
                        } else if (op.equals(FUNCTION_NAME_GETNEXTREV)) {
401
                            getNextRevision(identifierId);
402
                            status = true;
403
                        } else if (op.equals(FUNCTION_NAME_GETNEXTOBJ)) {
404
                            getNextObject();
405
                            status = true;
406
                        } 
407

    
408
                    } else if (httpVerb == PUT) {
409
                        //Earthgrid API > Identifier Service > addLSID Function 
410
                        response.setStatus(501);
411
                        printError(
412
                                "This method is not supported by metacat.  To "
413
                                + "add a new LSID, add a document to metacat.",
414
                                response);
415
                        status = true;
416
                    }
417

    
418
                } else if (resource.equals(RESOURCE_LOG)) {
419
                    System.out.println("Using resource 'log'");
420
                    //handle log events
421
                    if(httpVerb == GET)
422
                    {
423
                        getLog();
424
                        status = true;
425
                    }
426
                    else
427
                    {
428
                        //change to D1 spec for specifying which http methods are allowed for a resource
429
                        response.setStatus(501);
430
                        printError("POST, PUT, DELETE is not supported for logs.", response);
431
                        status = true;
432
                    }
433

    
434
                } else if(resource.equals(RESOURCE_CHECKSUM)) {
435
                    System.out.println("Using resource 'checksum'");
436
                    //handle checksum requests
437
                    if(httpVerb == GET)
438
                    {
439
                        String checksumAlgorithm = "MD5";
440
                    
441
                        String guid = request.getPathInfo();
442
                        if (guid != null && guid.length() > 1)
443
                            guid = request.getPathInfo().substring(1); //trim the slash
444
                        
445
                        Identifier guidid = new Identifier();
446
                        guidid.setValue(guid);
447
                        AuthToken token = new AuthToken(sessionId);
448
                        try
449
                        {
450
                            checksumAlgorithm = params.get("checksumAlgorithm")[0];
451
                        }
452
                        catch(Exception e)
453
                        {
454
                            //do nothing.  default to MD5
455
                        }
456
                        System.out.println("getting checksum for object " + guid +
457
                                " with algorithm " + checksumAlgorithm);
458
                        try
459
                        {
460
                            Checksum c = CrudService.getInstance().getChecksum(token, guidid, checksumAlgorithm);
461
                            System.out.println("got checksum " + c.getValue());
462
                            response.setStatus(200);
463
                            System.out.println("serializing response");
464
                            serializeServiceType(Checksum.class, c, response.getOutputStream());
465
                            System.out.println("done serializing response.");
466
                        }
467
                        catch(NotAuthorized na)
468
                        {
469
                            na.setDetail_code("1400");
470
                            serializeException(na, response.getOutputStream());
471
                        }
472
                        catch(NotFound nf)
473
                        {
474
                            nf.setDetail_code("1420");
475
                            serializeException(nf, response.getOutputStream());
476
                        }
477
                        catch(InvalidRequest ir)
478
                        {
479
                            ir.setDetail_code("1402");
480
                            serializeException(ir, response.getOutputStream());
481
                        }
482
                        catch(ServiceFailure sf)
483
                        {
484
                            sf.setDetail_code("1410");
485
                            serializeException(sf, response.getOutputStream());
486
                        }
487
                        catch(InvalidToken it)
488
                        {
489
                            it.setDetail_code("1430");
490
                            serializeException(it, response.getOutputStream());
491
                        }
492
                        status = true;
493
                    }
494
                } else if(resource.equals(RESOURCE_MONITOR)) {
495
                    //health monitoring calls
496
                    System.out.println("processing monitor request");
497
                    String pathInfo = request.getPathInfo();
498
                    if(httpVerb == GET)
499
                    {
500
                        System.out.println("verb is GET");
501
                        System.out.println("pathInfo is " + pathInfo);
502
                        pathInfo = pathInfo.substring(1);
503
                        HealthService hs = new HealthService(request, response);
504
                        if (pathInfo.toLowerCase().equals("ping")) {
505
                            System.out.println("processing ping request");
506
                            hs.ping();
507
                        } else if (pathInfo.toLowerCase().equals("status")) {
508
                            System.out.println("processing status request");
509
                            hs.getStatus();
510
                        } else if (pathInfo.toLowerCase().equals("object")) {
511
                            System.out.println("processing object request");
512
                            boolean day = false;
513
                            Identifier pid = null;
514
                            String url = null;
515
                            ObjectFormat of = null;
516
                            Date time = null;
517
                            
518
                            if(params.containsKey("day"))
519
                            {
520
                               day = true; 
521
                            }
522
                            if(params.containsKey("pid"))
523
                            {
524
                                String id = params.get("pid")[0];
525
                                pid = new Identifier();
526
                                pid.setValue(id);
527
                            }
528
                            if(params.containsKey("url"))
529
                            {
530
                                url = params.get("url")[0];
531
                            }
532
                            if(params.containsKey("format"))
533
                            {
534
                                String format = params.get("format")[0];
535
                                of = ObjectFormat.convert(format);
536
                            }
537
                            if(params.containsKey("time"))
538
                            {
539
                                String t = params.get("time")[0];
540
                                time = dateFormat.parse(t);
541
                            }
542
                            
543
                            hs.getObjectStatistics(day, pid, url, of, time);
544
                        } else if (pathInfo.toLowerCase().equals("event")) {
545
                            System.out.println("processing event request");
546
                            boolean day = false;
547
                            Identifier pid = null;
548
                            Date created = null;
549
                            ObjectFormat of = null;
550
                            Date time = null;
551
                            String ipAddress = null;
552
                            String event = null;
553
                            
554
                            if(params.containsKey("day"))
555
                            {
556
                               day = true; 
557
                            }
558
                            if(params.containsKey("pid"))
559
                            {
560
                                String id = params.get("pid")[0];
561
                                pid = new Identifier();
562
                                pid.setValue(id);
563
                            }
564
                            if(params.containsKey("created"))
565
                            {
566
                                String t = params.get("created")[0];
567
                                created = dateFormat.parse(t);
568
                            }
569
                            if(params.containsKey("format"))
570
                            {
571
                                String format = params.get("format")[0];
572
                                of = ObjectFormat.convert(format);
573
                            }
574
                            if(params.containsKey("eventtime"))
575
                            {
576
                                String t = params.get("eventtime")[0];
577
                                time = dateFormat.parse(t);
578
                            }
579
                            if(params.containsKey("ip_address"))
580
                            {
581
                                ipAddress = params.get("ip_address")[0];
582
                            }
583
                            if(params.containsKey("event"))
584
                            {
585
                                event = params.get("event")[0];
586
                            }
587
                            
588
                            hs.getOperationStatistics(day, pid, of, created, time, ipAddress, event);
589
                        }
590
                    }
591
                    status = true;
592
                } else if(resource.equals(RESOURCE_REPLICATE)) {
593
                    System.out.println("processing replicate request");
594
                    replicate(httpVerb, request, response);
595
                    status = true;
596
                }
597
                    
598
                if (!status)
599
                {
600
                    response.setStatus(400);
601
                    printError("Incorrect parameters!", response);
602
                }
603
            } else {
604
                response.setStatus(400);
605
                printError("Incorrect resource!", response);
606
            }
607
        } catch (Exception e) {
608
            logMetacat.error(e.getClass() + ": " + e.getMessage());
609
            System.out.println("Error in ResourceHandler.handle(): " + e.getClass() + ": " + e.getMessage());
610
            e.printStackTrace();
611
        }
612
    }
613
    
614
    /**
615
     * handle the /replicate action
616
     * @param httpVerb
617
     * @param request
618
     * @param response
619
     * @throws Exception
620
     */
621
    private void replicate(int httpVerb, HttpServletRequest request, HttpServletResponse response)
622
        throws Exception
623
    {
624
        if(httpVerb == POST)
625
        {
626
            System.out.println("in POST replicate()");
627
            /*InputStream is = request.getInputStream();
628
            String input = IOUtils.toString(is);
629
            System.out.println("input: " + input);
630
            is = IOUtils.toInputStream(input);*/
631
            
632
            File tmpDir = getTempDirectory();
633
            File tmpSMFile = new File(tmpDir + 
634
                    ".sysmeta." + new Date().getTime() + ".tmp");
635
            System.out.println("temp dir: " + tmpDir.getAbsolutePath());
636
            MultipartRequestResolver mrr = new MultipartRequestResolver(
637
                    tmpDir.getAbsolutePath(), 1000000000, 0);
638
            MultipartRequest mr = mrr.resolveMultipart(request);
639
            Map<String, File> files = mr.getMultipartFiles();
640
            Iterator keys = files.keySet().iterator();
641
            while(keys.hasNext())
642
            {
643
                String key = (String)keys.next();
644
                System.out.println("files key: " + key);
645
                System.out.println("files value: " + files.get(key));
646
            }
647
            
648
            Map<String, List<String>> params = mr.getMultipartParameters();
649
            keys = params.keySet().iterator();
650
            while(keys.hasNext())
651
            {
652
                String key = (String)keys.next();
653
                System.out.println("params key: " + key);
654
                System.out.println("params value: " + params.get(key));
655
            }
656
            
657
            //File f = files.get("sysmeta");
658
            //the files are not being keyed by the part name, but rather the filename
659
            File f = files.get(files.keySet().iterator().next());
660
            
661
            System.out.println("file: " + f.getAbsolutePath());
662
            String sourceNode = params.get("sourceNode").get(0);
663
            System.out.println("sourceNode: " + sourceNode);
664
            FileInputStream fis = new FileInputStream(f);
665
            
666
            //lookup the id in the registry
667
            URL url = new URL("http://cn.dataone.org/cn/node");
668
            InputStream urlis = url.openStream();
669
            Map<String,String> m = NodeListParser.parseNodeListFile(urlis);
670
            String nodeUrl = m.get(sourceNode);
671
            System.out.println("sourceNodeId: " + sourceNode);
672
            System.out.println("resolved sourceNodeUrl: " + nodeUrl);
673
            
674
            if(nodeUrl == null)
675
            {
676
                response.setStatus(500);
677
                response.getOutputStream().write(("Member Node id " + 
678
                        sourceNode + " not found in node registry.").getBytes());
679
                response.getOutputStream().close();
680
            }
681
            
682
            //respond to cn with 200/OK
683
            //String s;
684
            //s = "sysmeta: " + IOUtils.toString(fis);
685
            //s += "\n\n";
686
            response.setStatus(200);
687
            //response.getOutputStream().write(("sourceNode: " + sourceNode + "\n\n").getBytes());
688
            //response.getOutputStream().write(("s: " + s).getBytes());
689
            OutputStream out = response.getOutputStream();
690
            out.write("OK\n".getBytes());
691
            out.write(("sourceNodeId: " + sourceNode + "\n").getBytes());
692
            out.write(("sourceNodeUrl: " + nodeUrl + "\n").getBytes());
693
            out.close();
694
            
695
            //parse the systemMetadata
696
            SystemMetadata sm = (SystemMetadata)deserializeServiceType(SystemMetadata.class, fis);
697
            NodeReference nr = sm.getOriginMemberNode();
698
            nr.setValue(sourceNode);
699
            sm.setOriginMemberNode(nr);
700
            //get the document
701
            AuthToken token = new AuthToken(sessionId);
702
            MNode mnode = new MNode(nodeUrl);
703
            //get the doc from the remote host
704
            InputStream docStream = mnode.get(new AuthToken("public"), sm.getIdentifier());
705
            File outputTmpFile = getTempFile();
706
            System.out.println("wrote xml file to " + outputTmpFile.getAbsolutePath());
707
            FileOutputStream outputTmpFileStream = new FileOutputStream(outputTmpFile);
708
            IOUtils.copy(docStream, outputTmpFileStream);
709
            
710
            //verify checksum
711
            System.out.println("verifying checksum");
712
            Checksum sourceFileChecksum = ServiceTypeUtil.checksum(new FileInputStream(outputTmpFile), 
713
                    sm.getChecksum().getAlgorithm());
714
            
715
            String cs1 = sm.getChecksum().getValue();
716
            String cs2 = sourceFileChecksum.getValue();
717
            System.out.println("original checksum: " + cs1);
718
            System.out.println(" created checksum: " + cs2);
719
            
720
            if(!cs1.equals(cs2))
721
            {
722
                System.out.println("ERROR: Checksums do not match!");
723
            }
724
            
725
            //insert the document in local db
726
            //System.out.println("creating new doc");
727
            //CrudService.getInstance().create(token, 
728
            //        sm.getIdentifier(), new FileInputStream(outputTmpFile), sm);
729
            //call cn.setReplicationStatus(guid, COMPLETE)
730
            
731
        }
732
    }
733
    
734
    /**
735
     * create the root node registry response.  
736
     * @throws JiBXException
737
     * @throws IOException
738
     */
739
    private void createNodeResponse() 
740
        throws JiBXException, IOException
741
    {
742
        String nodeName = null;
743
        String nodeId = null;
744
        String nodeUrl = null;
745
        String nodeDesc = null;
746
        String nodeType = null;
747
        
748
        try
749
        {
750
            nodeId = PropertyService.getProperty("dataone.memberNodeId");
751
            nodeName = PropertyService.getProperty("dataone.nodeName");
752
            nodeUrl = SystemUtil.getContextURL() + "/d1/";
753
            nodeDesc = PropertyService.getProperty("dataone.nodeDescription");
754
            nodeType = PropertyService.getProperty("dataone.nodeType");
755
        }
756
        catch(PropertyNotFoundException pnfe)
757
        {
758
            logMetacat.error("createNodeResponse: " +
759
                    "property not found: " + pnfe.getMessage());
760
        }
761
        
762
        NodeList nl = new NodeList();
763
        Node n = new Node();
764
        NodeReference nr = new NodeReference();
765
        nr.setValue(nodeId);
766
        n.setIdentifier(nr);
767
        n.setBaseURL(nodeUrl);
768
        n.setDescription(nodeDesc);
769
        n.setName(nodeName + " -- WAR version WARVERSION");
770
        n.setType(NodeType.convert(nodeType));
771
        
772
        //create the services
773
        Service mnCrud03 = new Service();
774
        mnCrud03.setName("Metacat MN_Crud Services Version 0.3");
775
        mnCrud03.setVersion("0.3");
776
        
777
        Service mnCrud04 = new Service();
778
        mnCrud04.setName("Metacat MN_Crud Services Version 0.4");
779
        mnCrud04.setVersion("0.4");
780
        
781
        Service mnCrud09 = new Service();
782
        mnCrud09.setName("Metacat MN_Crud Services Version 0.9");
783
        mnCrud09.setVersion("0.9");
784
        
785
        Service mnReplication03 = new Service();
786
        mnReplication03.setName("Metcat MN_Replication Version 0.3");
787
        mnReplication03.setVersion("0.3");
788
        
789
        Service mnHealth04 = new Service();
790
        mnHealth04.setName("Metacat MN_Health Version 0.4");
791
        mnHealth04.setVersion("0.4");
792
        
793
        Service mnHealth06 = new Service();
794
        mnHealth06.setName("Metacat MN_Health Version 0.6");
795
        mnHealth06.setVersion("0.6");
796
        
797
        Service mnAuthentication07 = new Service();
798
        mnAuthentication07.setName("Metacat MN_Authentication Version 0.7");
799
        mnAuthentication07.setVersion("0.7");
800
        
801
        Service mnAuthorization07 = new Service();
802
        mnAuthorization07.setName("Metacat MN_Authorization Version 0.7");
803
        mnAuthorization07.setVersion("0.7");
804
        
805
                                    //name, rest, implemented
806
        mnCrud03.addMethod(getServiceMethod("MN_crud.get()", "/object/<guid>", true));
807
        mnCrud03.addMethod(getServiceMethod("MN_crud.getSystemMetadata()", "/meta/<guid>", true));
808
        mnCrud04.addMethod(getServiceMethod("MN_crud.create()", "/object/<guid>", true));
809
        mnCrud04.addMethod(getServiceMethod("MN_crud.update()", "/object/<guid>", true));
810
        mnCrud09.addMethod(getServiceMethod("MN_crud.delete()", "/object/<guid>", true));
811
        mnCrud03.addMethod(getServiceMethod("MN_crud.describe()", "/object/<guid>", true));
812
        mnCrud03.addMethod(getServiceMethod("MN_crud.getChecksum()", "/checksum/<guid>", true));
813
        mnCrud03.addMethod(getServiceMethod("MN_crud.getLogRecords()", "/log", true));
814
        mnReplication03.addMethod(getServiceMethod("MN_replication.listObjects()", "/object", true));
815
        mnReplication03.addMethod(getServiceMethod("MN_replication.replicate()", "/object", true));
816
        mnHealth04.addMethod(getServiceMethod("MN_health.ping()", "/health/ping", false));
817
        mnHealth04.addMethod(getServiceMethod("MN_health.getObjectStatistics()", "/monitor/object/<guid>", false));
818
        mnHealth06.addMethod(getServiceMethod("MN_health.getStatus()", "/health/status", false));
819
        mnAuthentication07.addMethod(getServiceMethod("MN_authentication.login()", "/account/login", false));
820
        mnAuthentication07.addMethod(getServiceMethod("MN_authentication.logout()", "/account/logout", false));
821
        mnAuthorization07.addMethod(getServiceMethod("MN_authorization.isAuthorized()", "/isAuthorized/<guid>", false));
822
        
823
        Services ss = new Services();
824
        ss.addService(mnCrud03);
825
        ss.addService(mnCrud04);
826
        ss.addService(mnCrud09);
827
        ss.addService(mnReplication03);
828
        ss.addService(mnHealth04);
829
        ss.addService(mnHealth06);
830
        ss.addService(mnAuthentication07);
831
        ss.addService(mnAuthorization07);
832
        nl.addNode(n);
833
        response.setContentType("text/xml");
834
        response.setStatus(200);
835
        serializeServiceType(NodeList.class, nl, response.getOutputStream());
836
    }
837
    
838
    /**
839
     * MN_crud.describe()
840
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
841
     * @param guid
842
     */
843
    private void describeObject(String guid)
844
    {
845
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
846
        OutputStream out = null;
847
        try
848
        {
849
            out = response.getOutputStream();
850
        }
851
        catch(Exception e)
852
        {
853
            logMetacat.error("Error getting output stream in ResourceHandler.describeObject: " + e.getClass() + ": " + e.getMessage());
854
            return;
855
        }
856
        response.setStatus(200);
857
        response.setContentType("text/xml");
858
        AuthToken token = new AuthToken(sessionId);
859
        CrudService cs = CrudService.getInstance();
860
        Identifier id = new Identifier();
861
        id.setValue(guid);
862
        try
863
        {
864
            DescribeResponse dr = cs.describe(token, id);
865
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SZ");
866
            response.addHeader("guid", guid);
867
            response.addHeader("checksum", dr.getDataONE_Checksum().getValue());
868
            response.addHeader("checksum_algorithm", dr.getDataONE_Checksum().getAlgorithm().name());
869
            response.addHeader("content_length", dr.getContent_Length() + "");
870
            response.addHeader("last_modified", dateFormat.format(dr.getLast_Modified()));
871
            response.addHeader("format", dr.getDataONE_ObjectFormat().toString());
872
        }
873
        catch(InvalidRequest ir)
874
        {
875
            serializeException(ir, out);
876
        }
877
        catch(NotImplemented ni)
878
        {
879
            serializeException(ni, out);
880
        }
881
        catch(NotAuthorized na)
882
        {
883
            serializeException(na, out);
884
        }
885
        catch(ServiceFailure sf)
886
        {
887
            serializeException(sf, out);
888
        }
889
        catch(NotFound nf)
890
        {
891
            serializeException(nf, out);
892
        }
893
        catch(InvalidToken it)
894
        {
895
            serializeException(it, out);
896
        }
897
    }
898
    
899
    /**
900
     * get the logs from the CrudService based on passed params.  Available 
901
     * params are token, fromDate, toDate, event.  See 
902
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
903
     * for more info
904
     */
905
    private void getLog()
906
    {
907
        OutputStream out = null;
908
        try
909
        {
910
            out = response.getOutputStream();
911
            response.setStatus(200);
912
            response.setContentType("text/xml");
913
            AuthToken token = new AuthToken(sessionId);
914
            String fromDateS = params.get("fromDate")[0];
915
            System.out.println("param fromDateS: " + fromDateS);
916
            Date fromDate = null;
917
            String toDateS = params.get("toDate")[0];
918
            System.out.println("param toDateS: " + toDateS);
919
            Date toDate = null;
920
            String eventS = params.get("event")[0];
921
            Event event = null;
922
            if(fromDateS != null)
923
            {
924
                //fromDate = dateFormat.parse(fromDateS);
925
                fromDate = parseDateAndConvertToGMT(fromDateS);
926
            }
927
            if(toDateS != null)
928
            {
929
                //toDate = dateFormat.parse(toDateS);
930
                toDate = parseDateAndConvertToGMT(toDateS);
931
            }
932
            if(eventS != null)
933
            {
934
                event = Event.convert(eventS);
935
            }
936
            System.out.println("fromDate: " + fromDate + " toDate: " + toDate);
937
            
938
            System.out.println("calling crudservice.getLogRecords");
939
            Log log = CrudService.getInstance().getLogRecords(token, fromDate, toDate, event);
940
            serializeServiceType(Log.class, log, out);
941
        }
942
        catch(Exception e)
943
        {
944
            String msg = "Could not get logs from CrudService: " + e.getClass() + ": " + e.getMessage();
945
            response.setStatus(500);
946
            ServiceFailure sf = new ServiceFailure("1490", msg);
947
            logMetacat.error(msg);
948
            e.printStackTrace();
949
            serializeException(sf, out);
950
        }
951
    }
952
    
953
    /**
954
     *  copies request parameters to a hashtable which is given as argument to native metacathandler functions  
955
     */
956
    private void initParams() {
957

    
958
        String name = null;
959
        String[] value = null;
960
        Enumeration paramlist = request.getParameterNames();
961
        while (paramlist.hasMoreElements()) {
962
            name = (String) paramlist.nextElement();
963
            value = request.getParameterValues(name);
964
            params.put(name, value);
965
        }
966
    }
967

    
968
    /**
969
     * 
970
     * Load user details of metacat session from the request 
971
     * 
972
     */
973
    private void loadSessionData()
974
      throws Exception
975
    {
976
        SessionData sessionData = RequestUtil.getSessionData(request);
977
        try
978
        {
979
            username = null;
980
            password = null;
981
            groupNames = null;
982
            sessionId = null;
983
            
984
            boolean validSession = false;
985
            SessionService ss = SessionService.getInstance();
986
            System.out.println("sessionData: " + sessionData);
987
            if(sessionData == null)
988
            {
989
                username = "public";
990
                sessionId = "0";
991
                System.out.println("sessiondata is null.  Creating a public session.");
992
                return;
993
            }
994
            
995
            System.out.println("username: " + sessionData.getUserName());
996
            System.out.println("sessionid: " + sessionData.getId());
997
            //validate the session
998
            if(ss.isSessionRegistered(sessionData.getId()) && 
999
               !(sessionData.getUserName().equals("public") || sessionData.getId().equals("0")))
1000
            {
1001
                validSession = true;
1002
            }
1003
            
1004
            if(validSession)
1005
            {
1006
                //if the session is valid, set these variables
1007
                username = sessionData.getUserName();
1008
                password = sessionData.getPassword();
1009
                groupNames = sessionData.getGroupNames();
1010
                sessionId = sessionData.getId();
1011
                System.out.println("setting sessionid to " + sessionId);
1012
                System.out.println("username: " + username);
1013
            }
1014
            
1015
            //if the session is not valid or the username is null, set
1016
            //username to public
1017
            if (username == null) 
1018
            {
1019
                System.out.println("setting username to public.");
1020
                username = "public";
1021
            }
1022
        }
1023
        catch(Exception e)
1024
        {
1025
            e.printStackTrace();
1026
            throw new Exception("Could not load the session data: " + e.getClass() + ": " + e.getMessage());
1027
        }
1028
    }
1029
    
1030
    /**
1031
     * generate missing system metadata for any science metadata objects
1032
     * that don't already have it. https://trac.dataone.org/ticket/591
1033
     * 
1034
     * called with POST meta/?op=generatemissingsystemmetadata
1035
     * @throws SQLException 
1036
     * @throws AccessionNumberException 
1037
     * @throws NoSuchAlgorithmException 
1038
     * @throws InvalidRequest 
1039
     * @throws NotImplemented 
1040
     * @throws NotFound 
1041
     * @throws NotAuthorized 
1042
     * @throws InvalidToken 
1043
     * @throws PropertyNotFoundException 
1044
     * @throws McdbDocNotFoundException 
1045
     * @throws ServiceFailure 
1046
     */
1047
    private void generateMissingSystemMetadata() throws ServiceFailure, McdbDocNotFoundException, PropertyNotFoundException,
1048
    InvalidToken, NotAuthorized, NotFound, NotImplemented, InvalidRequest, NoSuchAlgorithmException,
1049
    AccessionNumberException, SQLException
1050
    {
1051
        AuthToken token = new AuthToken(sessionId);
1052
        CrudService.getInstance().generateMissingSystemMetadata(token);
1053
    }
1054

    
1055
    /**
1056
     *  Earthgrid API > Identifier Service > isRegistered Function : 
1057
     *  calls MetacatHandler > handleIdIsRegisteredAction
1058
     * @param guid
1059
     * @throws IOException
1060
     */
1061
    private void isRegistered(String guid) throws IOException
1062
    {
1063
        
1064
        // Look up the localId for this guid
1065
        IdentifierManager im = IdentifierManager.getInstance();
1066
        String localId = "";
1067
        try {
1068
            localId = im.getLocalId(guid);
1069
        } catch (McdbDocNotFoundException e) {
1070
            // TODO: Need to return the proper DataONE exception
1071
        }
1072
        
1073
        params.put("docid", new String[] { localId });
1074
        PrintWriter out = response.getWriter();
1075
        response.setStatus(200);
1076
        response.setContentType("text/xml");
1077
        handler.handleIdIsRegisteredAction(out, params, response);
1078
        out.close();
1079
    }
1080

    
1081
    /**
1082
     * Earthgrid API > Identifier Service > getAllDocIds Function : 
1083
     * calls MetacatHandler > handleGetAllDocidsAction
1084
     * @throws IOException
1085
     */
1086
    private void getAllDocIds() throws IOException {
1087
        PrintWriter out = response.getWriter();
1088
        response.setStatus(200);
1089
        response.setContentType("text/xml");
1090
        handler.handleGetAllDocidsAction(out, params, response);
1091
        out.close();
1092
    }
1093

    
1094
    /**
1095
     * Earthgrid API > Identifier Service > getNextRevision Function : 
1096
     * calls MetacatHandler > handleGetRevisionAndDocTypeAction
1097
     * @param guid
1098
     * @throws IOException
1099
     */
1100
    private void getNextRevision(String guid) throws IOException 
1101
    {
1102
        params.put("docid", new String[] { guid });
1103
        PrintWriter out = response.getWriter();
1104
        response.setStatus(200);
1105
        response.setContentType("text/xml");
1106
        //handler.handleGetRevisionAndDocTypeAction(out, params);
1107

    
1108
        try {
1109
            // Make sure there is a docid
1110
            if (guid == null || guid.equals("")) {
1111
                throw new Exception("User didn't specify docid!");
1112
            }
1113

    
1114
            // Look up the localId for this guid
1115
            IdentifierManager im = IdentifierManager.getInstance();
1116
            String localId = "";
1117
            try {
1118
                localId = im.getLocalId(guid);
1119
            } catch (McdbDocNotFoundException e) {
1120
                // TODO: Need to return the proper DataONE exception
1121
            }
1122
           
1123
            // Create a DBUtil object
1124
            DBUtil dbutil = new DBUtil();
1125
            // Get a rev and doctype
1126
            String revAndDocType = dbutil
1127
                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
1128
            int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
1129

    
1130
            out.println("<?xml version=\"1.0\"?>");
1131
            out.print("<next-revision>");
1132
            out.print(revision);
1133
            out.print("</next-revision>");
1134

    
1135
        } catch (Exception e) {
1136
            // Handle exception
1137
            response.setStatus(500);
1138
            out.println("<?xml version=\"1.0\"?>");
1139
            out.println("<error>");
1140
            out.println(e.getClass() + ": " + e.getMessage());
1141
            out.println("</error>");
1142
        }
1143

    
1144
        out.close();
1145
    }
1146

    
1147
    /**
1148
     * Earthgrid API > Identifier Service > getNextObject Function : 
1149
     * calls MetacatHandler > handleGetMaxDocidAction
1150
     * @throws IOException
1151
     */
1152
    private void getNextObject() throws IOException {
1153
        PrintWriter out = response.getWriter();
1154
        response.setStatus(200);
1155
        response.setContentType("text/xml");
1156
        handler.handleGetMaxDocidAction(out, params, response);
1157
        out.close();
1158
    }
1159

    
1160
    /**
1161
     * Implements REST version of DataONE CRUD API --> get
1162
     * @param guid ID of data object to be read
1163
     */
1164
    private void getObject(String guid) {
1165
        CrudService cs = CrudService.getInstance();
1166
        cs.setParamsFromRequest(request);
1167
        AuthToken token = new AuthToken(sessionId);
1168
        OutputStream out = null;
1169
        try {
1170
            out = response.getOutputStream();
1171
            response.setStatus(200);
1172
            
1173
            if(guid != null)
1174
            { //get a specific document                
1175
                Identifier id = new Identifier();
1176
                id.setValue(guid);
1177
                try
1178
                {
1179
                    if(token == null)
1180
                    {
1181
                        token = new AuthToken("Public");
1182
                    }
1183
                    SystemMetadata sm = cs.getSystemMetadata(token, id);
1184
                    
1185
                    //set the content type
1186
                    if(sm.getObjectFormat().toString().trim().equals(ObjectFormat.TEXT_CSV.toString()))
1187
                    {
1188
                        response.setContentType("text/csv");
1189
                        response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".csv");
1190
                    }
1191
                    else if(sm.getObjectFormat().toString().trim().equals(ObjectFormat.TEXT_PLAIN.toString()))
1192
                    {
1193
                        response.setContentType("text/plain");
1194
                        response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".txt");
1195
                    } 
1196
                    else if(sm.getObjectFormat().toString().trim().equals(ObjectFormat.OCTET_STREAM.toString()))
1197
                    {
1198
                        response.setContentType("application/octet-stream");
1199
                    }
1200
                    else
1201
                    {
1202
                        response.setContentType("text/xml");
1203
                        response.setHeader("Content-Disposition", "inline; filename=" + id.getValue() + ".xml");
1204
                    }
1205
                    
1206
                    InputStream data = cs.get(token, id);
1207
                    IOUtils.copyLarge(data, response.getOutputStream());
1208
                }
1209
                catch(InvalidToken it)
1210
                {
1211
                    response.setStatus(500);
1212
                    serializeException(it, out); 
1213
                }
1214
                catch(ServiceFailure sf)
1215
                {
1216
                    response.setStatus(500);
1217
                    serializeException(sf, out); 
1218
                }
1219
                catch(NotAuthorized na)
1220
                {
1221
                    response.setStatus(500);
1222
                    serializeException(na, out); 
1223
                }
1224
                catch(NotFound nf)
1225
                {
1226
                    response.setStatus(500);
1227
                    serializeException(nf, out); 
1228
                }
1229
                catch(NotImplemented ni)
1230
                {
1231
                    response.setStatus(500);
1232
                    serializeException(ni, out); 
1233
                }
1234
                catch(Exception e)
1235
                {
1236
                    response.setStatus(500);
1237
                    System.out.println("Error with Crud.get().  " +
1238
                            "If this is an 'Exception producing data' error, " +
1239
                            "go to CrudService.get() for better debugging.  " +
1240
                            "Here's the error: " + e.getClass() + ": " + e.getMessage());
1241
                    e.printStackTrace();
1242
                    ServiceFailure sf = new ServiceFailure("1030", 
1243
                            "IO Error in ResourceHandler.getObject: " + e.getClass() + ": " + e.getMessage());
1244
                    serializeException(sf, out); 
1245
                }
1246
            }
1247
            else
1248
            { //call listObjects with specified params
1249
                Date startTime = null;
1250
                Date endTime = null;
1251
                ObjectFormat objectFormat = null;
1252
                boolean replicaStatus = false;
1253
                int start = 0;
1254
                //TODO: make the max count into a const
1255
                int count = 1000;
1256
                Enumeration paramlist = request.getParameterNames();
1257
                while (paramlist.hasMoreElements()) 
1258
                { //parse the params and make the crud call
1259
                    String name = (String) paramlist.nextElement();
1260
                    String[] value = (String[])request.getParameterValues(name);
1261
                    /*for(int i=0; i<value.length; i++)
1262
                    {
1263
                        System.out.println("name: " + name + " value: " + value[i]);
1264
                    }*/
1265
                    if(name.equals("startTime") && value != null)
1266
                    {
1267
                        try
1268
                        {
1269
                          //startTime = dateFormat.parse(value[0]);
1270
                            startTime = parseDateAndConvertToGMT(value[0]);
1271
                        }
1272
                        catch(Exception e)
1273
                        {  //if we can't parse it, just don't use the startTime param
1274
                            System.out.println("Could not parse startTime: " + value[0]);
1275
                            startTime = null;
1276
                        }
1277
                    }
1278
                    else if(name.equals("endTime") && value != null)
1279
                    {
1280
                        try
1281
                        {
1282
                          //endTime = dateFormat.parse(value[0]);
1283
                            endTime = parseDateAndConvertToGMT(value[0]);
1284
                        }
1285
                        catch(Exception e)
1286
                        {  //if we can't parse it, just don't use the endTime param
1287
                            System.out.println("Could not parse endTime: " + value[0]);
1288
                            endTime = null;
1289
                        }
1290
                    }
1291
                    else if(name.equals("objectFormat") && value != null) 
1292
                    {
1293
                        objectFormat = ObjectFormat.convert(value[0]);
1294
                    }
1295
                    else if(name.equals("replicaStatus") && value != null)
1296
                    {
1297
                        if(value != null && 
1298
                           value.length > 0 && 
1299
                           (value[0].equals("true") || value[0].equals("TRUE") || value[0].equals("YES")))
1300
                        {
1301
                            replicaStatus = true;
1302
                        }
1303
                    }
1304
                    else if(name.equals("start") && value != null)
1305
                    {
1306
                        start = new Integer(value[0]).intValue();
1307
                    }
1308
                    else if(name.equals("count") && value != null)
1309
                    {
1310
                        count = new Integer(value[0]).intValue();
1311
                    }
1312
                }
1313
                //make the crud call
1314
                System.out.println("token: " + token + " startTime: " + startTime +
1315
                        " endtime: " + endTime + " objectFormat: " + 
1316
                        objectFormat + " replicaStatus: " + replicaStatus + 
1317
                        " start: " + start + " count: " + count);
1318
               
1319
                ObjectList ol = cs.listObjects(token, startTime, endTime, 
1320
                        objectFormat, replicaStatus, start, count);
1321
                
1322
                StringReader sr = new StringReader(ol.toString());                
1323
                out = response.getOutputStream();  
1324
                response.setStatus(200);
1325
                response.setContentType("text/xml");
1326
                // Serialize and write it to the output stream
1327
                
1328
                try {
1329
                    serializeServiceType(ObjectList.class, ol, out);
1330
                } catch (JiBXException e) {
1331
                    throw new ServiceFailure("1190", "Failed to serialize ObjectList: " + e.getMessage());
1332
                }
1333
            }
1334
        } catch (BaseException e) {
1335
                response.setStatus(500);
1336
                serializeException(e, out);
1337
        } catch (IOException e) {
1338
            e.printStackTrace();
1339
            response.setStatus(500);
1340
            ServiceFailure sf = new ServiceFailure("1030", 
1341
                    "IO Error in ResourceHandler.getObject: " + e.getMessage());
1342
            serializeException(sf, out); 
1343
        } catch(NumberFormatException ne) {
1344
            response.setStatus(500);
1345
            InvalidRequest ir = new InvalidRequest("1030", "Invalid format for parameter: " + ne.getMessage());
1346
            serializeException(ir, out);
1347
        } catch (Exception e) {
1348
            e.printStackTrace();
1349
            response.setStatus(500);
1350
            ServiceFailure sf = new ServiceFailure("1030", 
1351
                    "Exception " + e.getClass().getName() + " raised while handling listObjects request: " + 
1352
                    e.getMessage());
1353
            serializeException(sf, out);
1354
        }
1355
    }
1356
    
1357
    /**
1358
     * parse a date and return it in GMT if it ends with a 'Z'
1359
     * @param date
1360
     * @return
1361
     * @throws ParseException
1362
     */
1363
    private Date parseDateAndConvertToGMT(String date) throws ParseException
1364
    {
1365
        try
1366
        {   //the format we want
1367
            return dateFormat.parse(date);
1368
        }
1369
        catch(java.text.ParseException pe)
1370
        {   //try another legacy format
1371
            DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
1372
            dateFormat2.setTimeZone(TimeZone.getTimeZone("GMT-0"));
1373
            return dateFormat2.parse(date);
1374
        }    
1375
    }
1376

    
1377
    /**
1378
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
1379
     * @param guid ID of data object to be read
1380
     */
1381
    private void getSystemMetadataObject(String guid) {
1382
        CrudService cs = CrudService.getInstance();
1383
        cs.setParamsFromRequest(request);
1384
        AuthToken token = new AuthToken(sessionId);
1385
        OutputStream out = null;
1386
        try {
1387
            response.setContentType("text/xml");
1388
            response.setStatus(200);
1389
            out = response.getOutputStream();
1390
            Identifier id = new Identifier();
1391
            id.setValue(guid);
1392
            SystemMetadata sysmeta = cs.getSystemMetadata(token, id);
1393
            
1394
            // Serialize and write it to the output stream
1395
            try {
1396
                //TODO: look at the efficiency of this method.  The system metadata
1397
                //is read from metacat (in CrudService) as xml, then serialized
1398
                //to a SystemMetadat object, then returned here, then serizlized
1399
                //back to XML to be sent to the response.
1400
                serializeServiceType(SystemMetadata.class, sysmeta, out);
1401
            } catch (JiBXException e) {
1402
                throw new ServiceFailure("1190", "Failed to serialize SystemMetadata: " + e.getMessage());
1403
            }
1404
        } catch (BaseException e) {
1405
            response.setStatus(500);
1406
                serializeException(e, out);
1407
        } catch (IOException e) {
1408
            response.setStatus(500);
1409
            ServiceFailure sf = new ServiceFailure("1030", 
1410
                    "IO Error in ResourceHandler.getSystemMetadataObject: " + e.getMessage());
1411
            serializeException(sf, out);
1412
        } finally {
1413
            IOUtils.closeQuietly(out);
1414
        }
1415
    }
1416
    
1417
    /**
1418
     * serialize an object of type to out
1419
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
1420
     * @param object the object to serialize
1421
     * @param out the stream to serialize it to
1422
     * @throws JiBXException
1423
     */
1424
    private void serializeServiceType(Class type, Object object, OutputStream out)
1425
      throws JiBXException
1426
    {
1427
        ServiceTypeUtil.serializeServiceType(type, object, out);
1428
    }
1429
    
1430
    /**
1431
     * deserialize an object of type from is
1432
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
1433
     * @param is the stream to deserialize from
1434
     * @throws JiBXException
1435
     */
1436
    private Object deserializeServiceType(Class type, InputStream is)
1437
      throws JiBXException
1438
    {
1439
        return ServiceTypeUtil.deserializeServiceType(type, is);
1440
    }
1441
    
1442
    /**
1443
     * Earthgrid API > Query Service > Query Function : translates ecogrid query document to metacat query 
1444
     * then calls DBQuery > createResultDocument function and then again translate resultset to ecogrid resultset
1445
     * 
1446
     * NOTE:
1447
     *      This is the only method that uses EcoGrid classes for its implementation.  
1448
     *      It does so because it takes an EcoGrid Query as input, and outputs an
1449
     *      EcoGrid ResultSet document.  These documents are parsed by the auto-generated
1450
     *      EcoGrid classes from axis, and so we link to them here rather than re-inventing them.
1451
     *      This creates a circular dependency, because the Metacat classes are needed
1452
     *      to build the EcoGrid implementation, and the EcoGrid jars are needed to build this query()
1453
     *      method.  This circularity could be resolved by moving the EcoGrid classes
1454
     *      to Metacat directly.  As we transition away from EcoGrid SOAP methods in
1455
     *      favor of these REST interfaces, this circular dependency can be eliminated.
1456
     *        
1457
     * @throws Exception
1458
     */
1459
    private void query() throws Exception {
1460
        /*  This block commented out because of the EcoGrid circular dependency.
1461
         *  For now, query will not be supported until the circularity can be
1462
         *  resolved, probably by moving the ecogrid query syntax transformers
1463
         *  directly into the Metacat codebase.  MBJ 2010-02-03
1464
         
1465
        try {
1466
            EcogridQueryParser parser = new EcogridQueryParser(request
1467
                    .getReader());
1468
            parser.parseXML();
1469
            QueryType queryType = parser.getEcogridQuery();
1470
            EcogridJavaToMetacatJavaQueryTransformer queryTransformer = 
1471
                new EcogridJavaToMetacatJavaQueryTransformer();
1472
            QuerySpecification metacatQuery = queryTransformer
1473
                    .transform(queryType);
1474

    
1475
            DBQuery metacat = new DBQuery();
1476

    
1477
            boolean useXMLIndex = (new Boolean(PropertyService
1478
                    .getProperty("database.usexmlindex"))).booleanValue();
1479
            String xmlquery = "query"; // we don't care the query in resultset,
1480
            // the query can be anything
1481
            PrintWriter out = null; // we don't want metacat result, so set out null
1482

    
1483
            // parameter: queryspecification, user, group, usingIndexOrNot
1484
            StringBuffer result = metacat.createResultDocument(xmlquery,
1485
                    metacatQuery, out, username, groupNames, useXMLIndex);
1486

    
1487
            // create result set transfer       
1488
            String saxparser = PropertyService.getProperty("xml.saxparser");
1489
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
1490
                    new StringReader(result.toString()), saxparser, queryType
1491
                            .getNamespace().get_value());
1492
            ResultsetType records = metacatResultsetParser.getEcogridResult();
1493

    
1494
            System.out
1495
                    .println(EcogridResultsetTransformer.toXMLString(records));
1496
            response.setContentType("text/xml");
1497
            out = response.getWriter();
1498
            out.print(EcogridResultsetTransformer.toXMLString(records));
1499

    
1500
        } catch (Exception e) {
1501
            e.printStackTrace();
1502
        }*/
1503
        response.setContentType("text/xml");
1504
        response.setStatus(501);
1505
        PrintWriter out = response.getWriter();
1506
        out.print("<error>Query operation not yet supported by Metacat.</error>");
1507
        out.close();
1508
    }
1509
    
1510
    private String streamToString(InputStream is)
1511
    throws IOException
1512
    {
1513
        return IOUtil.toString(is);
1514
    }
1515

    
1516
    private InputStream stringToStream(String s)
1517
    throws IOException
1518
    {
1519
        ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes(MetaCatServlet.DEFAULT_ENCODING));
1520
        return bais;
1521
    }
1522
    
1523
    /**
1524
     * locate the boundary marker for an MMP
1525
     * @param is
1526
     * @return
1527
     * @throws IOException
1528
     */
1529
    protected static String[] findBoundaryString(InputStream is)
1530
        throws IOException
1531
    {
1532
        String[] endResult = new String[2];
1533
        String boundary = "";
1534
        String searchString = "boundary=";
1535
        boolean doneWithCurrentArray = false;
1536
        byte[] b = new byte[1024];
1537
        int numbytes = is.read(b, 0, 1024);
1538

    
1539
        while(numbytes != -1)
1540
        {
1541
            String s = new String(b, 0, numbytes);
1542
            int searchStringIndex = s.indexOf(searchString);
1543
            
1544
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
1545
            { //the end of the boundary is in the next byte array
1546
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
1547
            }
1548
            else if(!boundary.startsWith("--"))
1549
            { //we can read the whole boundary from this byte array
1550
                boundary = s.substring(searchStringIndex + searchString.length() + 1, 
1551
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
1552
                boundary = "--" + boundary;
1553
                endResult[0] = boundary;
1554
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1555
                        s.length());
1556
                break;
1557
            }
1558
            else
1559
            { //we're now reading the 2nd byte array to get the rest of the boundary
1560
                searchString = "\"";
1561
                searchStringIndex = s.indexOf(searchString);
1562
                boundary += s.substring(0, searchStringIndex);
1563
                boundary = "--" + boundary;
1564
                endResult[0] = boundary;
1565
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1566
                        s.length());
1567
                break;
1568
            }
1569
        }
1570
        System.out.println("boundary is: '" + boundary + "'");
1571
        return endResult;
1572
    }
1573
    
1574
    /**
1575
     * return the directory where temp files are stored
1576
     * @return
1577
     */
1578
    private static File getTempDirectory()
1579
    {
1580
        File tmpDir = null;
1581
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
1582
        try
1583
        {
1584
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
1585
        }
1586
        catch(PropertyNotFoundException pnfe)
1587
        {
1588
            logMetacat.error("ResourceHandler.writeMMPPartstoFiles: " +
1589
                    "application.tmpDir not found.  Using /tmp instead.");
1590
            tmpDir = new File("/tmp");
1591
        }
1592
        return tmpDir;
1593
    }
1594
    
1595
    /**
1596
     * return a tmp file with a given name
1597
     * @param name
1598
     * @return
1599
     */
1600
    private static File getTempFile(String name)
1601
    {
1602
        File tmpDir = getTempDirectory();
1603
        File f = new File(tmpDir, name);
1604
        return f;
1605
    }
1606
    
1607
    /**
1608
     * return a temp file with a default name
1609
     * @return
1610
     */
1611
    private static File getTempFile()
1612
    {
1613
        return getTempFile(new Date().getTime() + ".tmp");
1614
    }
1615
    
1616
    /**
1617
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction 
1618
     * 
1619
     * @param guid - ID of data object to be inserted or updated.  If action is update, the pid
1620
     *               is the existing pid.  If insert, the pid is the new one
1621
     * @throws IOException
1622
     */
1623
    private void putObject(String pid, String action) {
1624
        System.out.println("ResourceHandler: putObject with pid " + pid);
1625
        logMetacat.debug("Entering putObject: " + pid + "/" + action);
1626
        OutputStream out = null;
1627
        try {
1628
            out = response.getOutputStream();
1629
            response.setStatus(200);
1630
            response.setContentType("text/xml");
1631
        } catch (IOException e1) {
1632
            logMetacat.error("Could not get the output stream for writing in putObject");
1633
        }
1634
        try {
1635
            
1636
            // Read the incoming data from its Mime Multipart encoding
1637
            logMetacat.debug("Disassembling MIME multipart form");
1638
            InputStream object = null;
1639
            InputStream sysmeta = null;
1640
            Map<String, List<String>> multipartparams;
1641
            
1642
            try
1643
            {
1644
                //String req = IOUtils.toString(request.getInputStream());
1645
                //System.out.println("request: " + req);
1646
                //InputStream reqStr = IOUtils.toInputStream(req);
1647
                InputStream reqStr = request.getInputStream();
1648
                
1649
                //handle MMP inputs
1650
                File tmpDir = getTempDirectory();
1651
                File tmpSMFile = new File(tmpDir + 
1652
                        ".sysmeta." + new Date().getTime() + ".tmp");
1653
                System.out.println("temp dir: " + tmpDir.getAbsolutePath());
1654
                MultipartRequestResolver mrr = new MultipartRequestResolver(
1655
                        tmpDir.getAbsolutePath(), 1000000000, 0);
1656
                MultipartRequest mr = mrr.resolveMultipart(request);
1657
                System.out.println("resolved multipart request");
1658
                Map<String, File> files = mr.getMultipartFiles();
1659
                if(files == null)
1660
                {
1661
                    throw new ServiceFailure("1202", "create/update must have multipart files with names 'object' and 'sysmeta'");
1662
                }
1663
                System.out.println("got multipart files");
1664
                
1665
                if(files.keySet() == null)
1666
                {
1667
                    System.out.println("No file keys in MMP request.");
1668
                    throw new ServiceFailure("1202", "No file keys found in MMP.  " +
1669
                            "create/update must have multipart files with names 'object' and 'sysmeta'");
1670
                }
1671

    
1672
		// for logging purposes, dump out the key-value pairs that constitute the request
1673
		// 3 types exist: request params, multipart params, and multipart files
1674
                Iterator it = files.keySet().iterator();
1675
                System.out.println("iterating through request parts: " + it);
1676
                while(it.hasNext())
1677
                {
1678
                    String key = (String)it.next();
1679
                    System.out.println("files key: " + key);
1680
                    System.out.println("files value: " + files.get(key));
1681
                }
1682
                
1683
                multipartparams = mr.getMultipartParameters();
1684
                it = multipartparams.keySet().iterator();
1685
                while(it.hasNext())
1686
                {
1687
                    String key = (String)it.next();
1688
                    System.out.println("multipartparams key: " + key);
1689
                    System.out.println("multipartparams value: " + multipartparams.get(key));
1690
                }
1691
                
1692
                it = params.keySet().iterator();
1693
                while(it.hasNext())
1694
                {
1695
                    String key = (String)it.next();
1696
                    System.out.println("param key: " + key);
1697
                    System.out.println("param value: " + params.get(key));
1698
                }
1699
		System.out.println("done iterating the request...");
1700

    
1701
                File smFile = files.get("sysmeta");
1702
		if (smFile == null) 
1703
		    throw new InvalidRequest("1102", "Missing the required file-part 'sysmeta' from the multipart request.");
1704
                System.out.println("smFile: " + smFile.getAbsolutePath());
1705
                sysmeta = new FileInputStream(smFile);
1706
                File objFile = files.get("object");
1707
		if (objFile == null) 
1708
		    throw new InvalidRequest("1102", "Missing the required file-part 'object' from the multipart request.");
1709

    
1710
                System.out.println("objectfile: " + objFile.getAbsolutePath());
1711
                object = new FileInputStream(objFile);
1712
                
1713
                /*String obj = IOUtils.toString(object);
1714
                String sm = IOUtils.toString(sysmeta);
1715
                System.out.println("object: " + obj);
1716
                System.out.println("sm: " + sm);
1717
                object = IOUtils.toInputStream(obj);
1718
                sysmeta = IOUtils.toInputStream(sm);*/
1719
                
1720
            }
1721
            catch(org.apache.commons.fileupload.FileUploadException fue)
1722
            {
1723
                throw new ServiceFailure("1202", "Could not upload MMP files: " + fue.getMessage());
1724
            }
1725
            catch(IOException ioe)
1726
            {
1727
                throw new ServiceFailure("1202", 
1728
                        "IOException when processing Mime Multipart: " + ioe.getMessage());
1729
            }
1730
            catch(Exception e)
1731
            {
1732
                throw new ServiceFailure("1202", "Error handling MMP upload: " + e.getClass() + ": " + e.getMessage());
1733
            }
1734
            
1735
            if ( action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
1736

    
1737
                // Check if the objectId exists
1738
                IdentifierManager im = IdentifierManager.getInstance();
1739
                if (im.identifierExists(pid)) {
1740
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + pid);
1741
                }
1742

    
1743
                logMetacat.debug("Commence creation...");
1744
                IBindingFactory bfact =
1745
                    BindingDirectory.getFactory(SystemMetadata.class);
1746
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1747
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1748

    
1749
                CrudService cs = CrudService.getInstance();
1750
                AuthToken token = new AuthToken(sessionId); 
1751
                cs.setParamsFromRequest(request);
1752
                Identifier id = new Identifier();
1753
                id.setValue(pid);
1754
                System.out.println("creating object with pid " + id.getValue());
1755
                Identifier rId = cs.create(token, id, object, smd);
1756
                serializeServiceType(Identifier.class, rId, out);
1757
                
1758
            } else if (action.equals(FUNCTION_NAME_UPDATE)) { //handle updates
1759

    
1760
            	// Check if the objectId exists
1761
                IdentifierManager im = IdentifierManager.getInstance();
1762
                if (!im.identifierExists(pid)) {
1763
                    throw new NotFound("1280", "The pid you are trying to update does not exist: " + pid);
1764
                }
1765
                // check that the newPid parameter was provided and it doesn't exist
1766
                if(multipartparams.get("newPid") == null)
1767
                    throw new InvalidRequest("1202", "'newPid' must be contained in the request parameters.");
1768
                String newPidString = multipartparams.get("newPid").get(0);
1769
                if (im.identifierExists(newPidString)) 
1770
                    throw new IdentifierNotUnique("1220", "Identifier is already in use: " + newPidString);
1771
               
1772
                
1773
                Identifier newPid = new Identifier();
1774
                Identifier obsoletedPid = new Identifier();
1775
                newPid.setValue(newPidString);
1776
                obsoletedPid.setValue(pid);
1777
               
1778
            	
1779
                CrudService cs = CrudService.getInstance();
1780
                AuthToken token = new AuthToken(sessionId);
1781

    
1782
                logMetacat.debug("Commence update...");
1783
                
1784
                //get the systemmetadata
1785
                IBindingFactory bfact =
1786
                	BindingDirectory.getFactory(SystemMetadata.class);
1787
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1788
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1789

    
1790
                cs.setParamsFromRequest(request);
1791
                Identifier rId = cs.update(token, newPid, object, obsoletedPid, smd);
1792
                serializeServiceType(Identifier.class, rId, out);
1793
            } else {
1794
                throw new InvalidRequest("1000", "Operation must be create or update.");
1795
            }
1796
            
1797
            //clean up the MMP files
1798
            //parts.get("systemmetadata").delete();
1799
            //parts.get("object").delete();
1800
        } catch (NotAuthorized e) {
1801
            response.setStatus(500);
1802
            serializeException(e, out);
1803
        } catch (InvalidToken e) {
1804
            response.setStatus(500);
1805
            serializeException(e, out);
1806
        } catch (ServiceFailure e) {
1807
            response.setStatus(500);
1808
            serializeException(e, out);
1809
        } catch (NotFound e) {
1810
            response.setStatus(500);
1811
            serializeException(e, out);
1812
        } catch (IdentifierNotUnique e) {
1813
            response.setStatus(500);
1814
            serializeException(e, out);
1815
        } catch (UnsupportedType e) {
1816
            response.setStatus(500);
1817
            serializeException(e, out);
1818
        } catch (InsufficientResources e) {
1819
            response.setStatus(500);
1820
            serializeException(e, out);
1821
        } catch (InvalidSystemMetadata e) {
1822
            response.setStatus(500);
1823
            serializeException(e, out);
1824
        } catch (NotImplemented e) {
1825
            response.setStatus(500);
1826
            serializeException(e, out);
1827
        } catch (InvalidRequest e) {
1828
            response.setStatus(500);
1829
            serializeException(e, out);
1830
        } /*catch (MessagingException e) {
1831
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1832
            serializeException(sf, out);
1833
        } catch (IOException e) {
1834
            response.setStatus(500);
1835
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1836
            serializeException(sf, out);
1837
        }*/ catch (JiBXException e) {
1838
            response.setStatus(500);
1839
            e.printStackTrace(System.out);
1840
            InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e.getMessage());
1841
            serializeException(ism, out);
1842
        }
1843
    }
1844

    
1845
    /**
1846
     * Handle delete 
1847
     * @param guid ID of data object to be deleted
1848
     * @throws IOException
1849
     */
1850
    private void deleteObject(String guid) throws IOException 
1851
    {
1852
        // Look up the localId for this global identifier
1853
        System.out.println("!!!!!!!!!!!!!!!!!deleting object " + guid);
1854
        IdentifierManager im = IdentifierManager.getInstance();
1855
        String localId = "";
1856
        OutputStream out = response.getOutputStream();
1857
        response.setStatus(200);
1858
        try {
1859
            localId = im.getLocalId(guid);
1860
        } catch (McdbDocNotFoundException e) {
1861
            NotFound nf = new NotFound("1340", "Document with guid " + guid + " not found.");
1862
            response.setStatus(404);
1863
            serializeException(nf, out);
1864
        }
1865
       
1866
        AuthToken token = new AuthToken(sessionId);
1867
        CrudService cs = CrudService.getInstance();
1868
        Identifier id = new Identifier();
1869
        id.setValue(guid);
1870
        try
1871
        {
1872
            System.out.println("Calling delete");
1873
            cs.delete(token, id);
1874
            serializeServiceType(Identifier.class, id, out);
1875
        } 
1876
        catch (NotAuthorized e) {
1877
            response.setStatus(500);
1878
            serializeException(e, out);
1879
        } catch (InvalidToken e) {
1880
            response.setStatus(500);
1881
            serializeException(e, out);
1882
        } catch (ServiceFailure e) {
1883
            response.setStatus(500);
1884
            serializeException(e, out);
1885
        } catch (NotImplemented e) {
1886
            response.setStatus(500);
1887
            serializeException(e, out);
1888
        } catch (InvalidRequest e) {
1889
            response.setStatus(500);
1890
            serializeException(e, out);
1891
        } catch(NotFound e) {
1892
            response.setStatus(500);
1893
            serializeException(e, out);
1894
        } catch(JiBXException e) {
1895
            response.setStatus(500);
1896
            serializeException(new ServiceFailure("1350", "JiBXException: " + e.getMessage()), out);
1897
        }
1898
        out.close();
1899
    }
1900
    
1901
    /**
1902
     * set the access perms on a document
1903
     * @throws IOException
1904
     */
1905
    private void setaccess() throws Exception
1906
    {
1907
        try
1908
        {
1909
            String guid = params.get("guid")[0];
1910
            Identifier id = new Identifier();
1911
            id.setValue(guid);
1912
            AuthToken token = new AuthToken(sessionId);
1913
            String principal = params.get("principal")[0];
1914
            String permission = params.get("permission")[0];
1915
            String permissionType = params.get("permissionType")[0];
1916
            String permissionOrder = params.get("permissionOrder")[0];
1917
            String setSystemMetadata = params.get("setsystemmetadata")[0];
1918
            boolean ssm = false;
1919
            if(setSystemMetadata.equals("true") || setSystemMetadata.equals("TRUE") ||
1920
                    setSystemMetadata.equals("yes"))
1921
            {
1922
                ssm = true;
1923
            }
1924
            CrudService cs = CrudService.getInstance();
1925
            //TODO: remove the setsystemmetadata param and set this so the systemmetadata always gets set
1926
            cs.setAccess(token, id, principal, permission, permissionType, permissionOrder, ssm);
1927
        }
1928
        catch(Exception e)
1929
        {
1930
            response.setStatus(500);
1931
            printError("Error setting access in ResourceHandler: " + e.getClass() + ": " + e.getMessage(), response);
1932
            throw e;
1933
        }
1934
    }
1935

    
1936
    /**
1937
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
1938
     * 
1939
     * @throws IOException
1940
     */
1941
    private void login() throws IOException {
1942
        PrintWriter out = response.getWriter();
1943
        response.setStatus(200);
1944
        response.setContentType("text/xml");
1945
        handler.handleLoginAction(out, params, request, response);
1946
        out.close();
1947
    }
1948

    
1949
    /**
1950
     * Earthgrid API > Authentication Service > Logout Function : calls MetacatHandler > handleLogoutAction
1951
     * 
1952
     * @throws IOException
1953
     */
1954
    private void logout() throws IOException {
1955
        PrintWriter out = response.getWriter();
1956
        response.setStatus(200);
1957
        response.setContentType("text/xml");
1958
        handler.handleLogoutAction(out, params, request, response);
1959
        out.close();
1960
    }
1961

    
1962
    /**
1963
     * Prints xml response
1964
     * @param message Message to be displayed
1965
     * @param response Servlet response that xml message will be printed 
1966
     * */
1967
    private void printError(String message, HttpServletResponse response) {
1968
        try {
1969
            logMetacat.error("ResourceHandler: Printing error to servlet response: " + message);
1970
            PrintWriter out = response.getWriter();
1971
            response.setContentType("text/xml");
1972
            out.println("<?xml version=\"1.0\"?>");
1973
            out.println("<error>");
1974
            out.println(message);
1975
            out.println("</error>");
1976
            out.close();
1977
        } catch (IOException e) {
1978
            e.printStackTrace();
1979
        }
1980
    }
1981
    
1982
    /**
1983
     * serialize a D1 exception using jibx
1984
     * @param e
1985
     * @param out
1986
     */
1987
    private void serializeException(BaseException e, OutputStream out) {
1988
        // TODO: Use content negotiation to determine which return format to use
1989
        response.setContentType("text/xml");
1990
        response.setStatus(e.getCode());
1991
        
1992
        logMetacat.error("ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
1993
        e.printStackTrace();
1994
        
1995
        try {
1996
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
1997
        } catch (IOException e1) {
1998
            logMetacat.error("Error writing exception to stream. " 
1999
                    + e1.getMessage());
2000
        }
2001
    }
2002
    
2003
    /**
2004
     * create a new ServiceMethod declaration
2005
     * @param name
2006
     * @param rest
2007
     * @param implemented
2008
     * @return
2009
     */
2010
    private ServiceMethod getServiceMethod(String name, String rest, boolean implemented)
2011
    {
2012
        ServiceMethod sm = new ServiceMethod();
2013
        sm.setImplemented(implemented);
2014
        sm.setName(name);
2015
        sm.setRest(rest);
2016
        return sm;
2017
    }
2018

    
2019
}
(4-4/5)