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
import java.text.DateFormat;
36
import java.text.ParseException;
37
import java.text.ParsePosition;
38
import java.text.SimpleDateFormat;
39

    
40

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

    
67
import edu.ucsb.nceas.metacat.DBUtil;
68
import edu.ucsb.nceas.metacat.IdentifierManager;
69
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
70
import edu.ucsb.nceas.metacat.MetaCatServlet;
71
import edu.ucsb.nceas.metacat.MetacatHandler;
72
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
73
import edu.ucsb.nceas.metacat.dataone.CrudService;
74
import edu.ucsb.nceas.metacat.dataone.HealthService;
75
import edu.ucsb.nceas.metacat.properties.PropertyService;
76
import edu.ucsb.nceas.metacat.service.SessionService;
77
import edu.ucsb.nceas.metacat.util.RequestUtil;
78
import edu.ucsb.nceas.metacat.util.SessionData;
79
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
80

    
81
import org.dataone.service.streaming.util.StreamUtil;
82

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

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

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

    
200
    /**HTTP Verb GET*/
201
    public static final byte GET = 1;
202
    /**HTTP Verb POST*/
203
    public static final byte POST = 2;
204
    /**HTTP Verb PUT*/
205
    public static final byte PUT = 3;
206
    /**HTTP Verb DELETE*/
207
    public static final byte DELETE = 4;
208
    /**HTTP Verb HEAD*/
209
    public static final byte HEAD = 5;
210

    
211
    /*
212
     * API Resources
213
     */
214
    private static final String RESOURCE_OBJECTS = "object";
215
    private static final String RESOURCE_META = "meta";
216
    private static final String RESOURCE_SESSION = "session";
217
    private static final String RESOURCE_IDENTIFIER = "identifier";
218
    private static final String RESOURCE_LOG = "log";
219
    private static final String RESOURCE_CHECKSUM = "checksum";
220
    private static final String RESOURCE_MONITOR = "monitor";
221
    private static final String RESOURCE_BASE_URL = "d1";
222
    private static final String RESOURCE_REPLICATE = "replicate";
223

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

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

    
251
    private Hashtable<String, String[]> params;
252

    
253
    /**Initializes new instance by setting servlet context,request and response*/
254
    public ResourceHandler(ServletContext servletContext,
255
            HttpServletRequest request, HttpServletResponse response) {
256
        this.servletContext = servletContext;
257
        this.request = request;
258
        this.response = response;
259
    }
260

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

    
289
            if (resource != null) {
290
                //resource = request.getServletPath().substring(1);
291

    
292
                params = new Hashtable<String, String[]>();
293
                initParams();
294

    
295
                Timer timer = new Timer();
296
                handler = new MetacatHandler(timer);
297

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

    
344
                } else if (resource.equals(RESOURCE_OBJECTS)) {
345
                    System.out.println("Using resource 'object'");
346
                    logMetacat.debug("D1 Rest: Starting resource processing...");
347
                    loadSessionData();
348

    
349
                    String objectId = request.getPathInfo();
350
                    if (objectId != null && objectId.length() > 1) 
351
                    {
352
                        objectId = request.getPathInfo().substring(1);
353
                    }
354
                    else
355
                    {
356
                        objectId = null;
357
                    }
358
                    
359
                    System.out.println("objectId in ReasourceHandler.handle: " + objectId);
360

    
361
                    logMetacat.debug("verb:" + httpVerb);
362

    
363
                    if (httpVerb == GET) {
364
                        getObject(objectId);
365
                        status = true;
366
                    } else if (httpVerb == POST) {
367
                        putObject(objectId, FUNCTION_NAME_INSERT);
368
                        status = true;
369
                    } else if (httpVerb == PUT) {
370
                        putObject(objectId, FUNCTION_NAME_UPDATE);
371
                        status = true;
372
                    } else if (httpVerb == DELETE) {
373
                        deleteObject(objectId);
374
                        status = true;
375
                    } else if (httpVerb == HEAD) {
376
                        describeObject(objectId);
377
                        status = true;
378
                    }
379
                    
380

    
381
                } else if (resource.equals(RESOURCE_IDENTIFIER)) {
382
                    System.out.println("Using resource 'identifier'");
383
                    String identifierId = request.getPathInfo();
384
                    if (identifierId != null && identifierId.length() > 1)
385
                        identifierId = request.getPathInfo().substring(1); //trim the slash
386

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

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

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

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

    
954
        String name = null;
955
        String[] value = null;
956
        Enumeration paramlist = request.getParameterNames();
957
        while (paramlist.hasMoreElements()) {
958
            name = (String) paramlist.nextElement();
959
            value = request.getParameterValues(name);
960
            params.put(name, value);
961
        }
962
    }
963

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

    
1038
    /**
1039
     *  Earthgrid API > Identifier Service > isRegistered Function : 
1040
     *  calls MetacatHandler > handleIdIsRegisteredAction
1041
     * @param guid
1042
     * @throws IOException
1043
     */
1044
    private void isRegistered(String guid) throws IOException
1045
    {
1046
        
1047
        // Look up the localId for this guid
1048
        IdentifierManager im = IdentifierManager.getInstance();
1049
        String localId = "";
1050
        try {
1051
            localId = im.getLocalId(guid);
1052
        } catch (McdbDocNotFoundException e) {
1053
            // TODO: Need to return the proper DataONE exception
1054
        }
1055
        
1056
        params.put("docid", new String[] { localId });
1057
        PrintWriter out = response.getWriter();
1058
        response.setStatus(200);
1059
        response.setContentType("text/xml");
1060
        handler.handleIdIsRegisteredAction(out, params, response);
1061
        out.close();
1062
    }
1063

    
1064
    /**
1065
     * Earthgrid API > Identifier Service > getAllDocIds Function : 
1066
     * calls MetacatHandler > handleGetAllDocidsAction
1067
     * @throws IOException
1068
     */
1069
    private void getAllDocIds() throws IOException {
1070
        PrintWriter out = response.getWriter();
1071
        response.setStatus(200);
1072
        response.setContentType("text/xml");
1073
        handler.handleGetAllDocidsAction(out, params, response);
1074
        out.close();
1075
    }
1076

    
1077
    /**
1078
     * Earthgrid API > Identifier Service > getNextRevision Function : 
1079
     * calls MetacatHandler > handleGetRevisionAndDocTypeAction
1080
     * @param guid
1081
     * @throws IOException
1082
     */
1083
    private void getNextRevision(String guid) throws IOException 
1084
    {
1085
        params.put("docid", new String[] { guid });
1086
        PrintWriter out = response.getWriter();
1087
        response.setStatus(200);
1088
        response.setContentType("text/xml");
1089
        //handler.handleGetRevisionAndDocTypeAction(out, params);
1090

    
1091
        try {
1092
            // Make sure there is a docid
1093
            if (guid == null || guid.equals("")) {
1094
                throw new Exception("User didn't specify docid!");
1095
            }
1096

    
1097
            // Look up the localId for this guid
1098
            IdentifierManager im = IdentifierManager.getInstance();
1099
            String localId = "";
1100
            try {
1101
                localId = im.getLocalId(guid);
1102
            } catch (McdbDocNotFoundException e) {
1103
                // TODO: Need to return the proper DataONE exception
1104
            }
1105
           
1106
            // Create a DBUtil object
1107
            DBUtil dbutil = new DBUtil();
1108
            // Get a rev and doctype
1109
            String revAndDocType = dbutil
1110
                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
1111
            int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
1112

    
1113
            out.println("<?xml version=\"1.0\"?>");
1114
            out.print("<next-revision>");
1115
            out.print(revision);
1116
            out.print("</next-revision>");
1117

    
1118
        } catch (Exception e) {
1119
            // Handle exception
1120
            response.setStatus(500);
1121
            out.println("<?xml version=\"1.0\"?>");
1122
            out.println("<error>");
1123
            out.println(e.getMessage());
1124
            out.println("</error>");
1125
        }
1126

    
1127
        out.close();
1128
    }
1129

    
1130
    /**
1131
     * Earthgrid API > Identifier Service > getNextObject Function : 
1132
     * calls MetacatHandler > handleGetMaxDocidAction
1133
     * @throws IOException
1134
     */
1135
    private void getNextObject() throws IOException {
1136
        PrintWriter out = response.getWriter();
1137
        response.setStatus(200);
1138
        response.setContentType("text/xml");
1139
        handler.handleGetMaxDocidAction(out, params, response);
1140
        out.close();
1141
    }
1142

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

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

    
1458
            DBQuery metacat = new DBQuery();
1459

    
1460
            boolean useXMLIndex = (new Boolean(PropertyService
1461
                    .getProperty("database.usexmlindex"))).booleanValue();
1462
            String xmlquery = "query"; // we don't care the query in resultset,
1463
            // the query can be anything
1464
            PrintWriter out = null; // we don't want metacat result, so set out null
1465

    
1466
            // parameter: queryspecification, user, group, usingIndexOrNot
1467
            StringBuffer result = metacat.createResultDocument(xmlquery,
1468
                    metacatQuery, out, username, groupNames, useXMLIndex);
1469

    
1470
            // create result set transfer       
1471
            String saxparser = PropertyService.getProperty("xml.saxparser");
1472
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
1473
                    new StringReader(result.toString()), saxparser, queryType
1474
                            .getNamespace().get_value());
1475
            ResultsetType records = metacatResultsetParser.getEcogridResult();
1476

    
1477
            System.out
1478
                    .println(EcogridResultsetTransformer.toXMLString(records));
1479
            response.setContentType("text/xml");
1480
            out = response.getWriter();
1481
            out.print(EcogridResultsetTransformer.toXMLString(records));
1482

    
1483
        } catch (Exception e) {
1484
            e.printStackTrace();
1485
        }*/
1486
        response.setContentType("text/xml");
1487
        response.setStatus(501);
1488
        PrintWriter out = response.getWriter();
1489
        out.print("<error>Query operation not yet supported by Metacat.</error>");
1490
        out.close();
1491
    }
1492
    
1493
    private String streamToString(InputStream is)
1494
    throws IOException
1495
    {
1496
        return IOUtil.toString(is);
1497
    }
1498

    
1499
    private InputStream stringToStream(String s)
1500
    throws IOException
1501
    {
1502
        ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes(MetaCatServlet.DEFAULT_ENCODING));
1503
        return bais;
1504
    }
1505
    
1506
    /**
1507
     * locate the boundary marker for an MMP
1508
     * @param is
1509
     * @return
1510
     * @throws IOException
1511
     */
1512
    protected static String[] findBoundaryString(InputStream is)
1513
        throws IOException
1514
    {
1515
        String[] endResult = new String[2];
1516
        String boundary = "";
1517
        String searchString = "boundary=";
1518
        boolean doneWithCurrentArray = false;
1519
        byte[] b = new byte[1024];
1520
        int numbytes = is.read(b, 0, 1024);
1521

    
1522
        while(numbytes != -1)
1523
        {
1524
            String s = new String(b, 0, numbytes);
1525
            int searchStringIndex = s.indexOf(searchString);
1526
            
1527
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
1528
            { //the end of the boundary is in the next byte array
1529
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
1530
            }
1531
            else if(!boundary.startsWith("--"))
1532
            { //we can read the whole boundary from this byte array
1533
                boundary = s.substring(searchStringIndex + searchString.length() + 1, 
1534
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
1535
                boundary = "--" + boundary;
1536
                endResult[0] = boundary;
1537
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1538
                        s.length());
1539
                break;
1540
            }
1541
            else
1542
            { //we're now reading the 2nd byte array to get the rest of the boundary
1543
                searchString = "\"";
1544
                searchStringIndex = s.indexOf(searchString);
1545
                boundary += s.substring(0, searchStringIndex);
1546
                boundary = "--" + boundary;
1547
                endResult[0] = boundary;
1548
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1549
                        s.length());
1550
                break;
1551
            }
1552
        }
1553
        System.out.println("boundary is: '" + boundary + "'");
1554
        return endResult;
1555
    }
1556
    
1557
    /**
1558
     * return the directory where temp files are stored
1559
     * @return
1560
     */
1561
    private static File getTempDirectory()
1562
    {
1563
        File tmpDir = null;
1564
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
1565
        try
1566
        {
1567
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
1568
        }
1569
        catch(PropertyNotFoundException pnfe)
1570
        {
1571
            logMetacat.error("ResourceHandler.writeMMPPartstoFiles: " +
1572
                    "application.tmpDir not found.  Using /tmp instead.");
1573
            tmpDir = new File("/tmp");
1574
        }
1575
        return tmpDir;
1576
    }
1577
    
1578
    /**
1579
     * return a tmp file with a given name
1580
     * @param name
1581
     * @return
1582
     */
1583
    private static File getTempFile(String name)
1584
    {
1585
        File tmpDir = getTempDirectory();
1586
        File f = new File(tmpDir, name);
1587
        return f;
1588
    }
1589
    
1590
    /**
1591
     * return a temp file with a default name
1592
     * @return
1593
     */
1594
    private static File getTempFile()
1595
    {
1596
        return getTempFile(new Date().getTime() + ".tmp");
1597
    }
1598
    
1599
    /**
1600
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction 
1601
     * 
1602
     * @param guid ID of data object to be inserted or updated
1603
     * @throws IOException
1604
     */
1605
    private void putObject(String guid, String action) {
1606
        System.out.println("ResourceHandler: putObject with guid " + guid);
1607
        logMetacat.debug("Entering putObject: " + guid + "/" + action);
1608
        OutputStream out = null;
1609
        try {
1610
            out = response.getOutputStream();
1611
            response.setStatus(200);
1612
            response.setContentType("text/xml");
1613
        } catch (IOException e1) {
1614
            logMetacat.error("Could not get the output stream for writing in putObject");
1615
        }
1616
        try {
1617
            
1618
            // Read the incoming data from its Mime Multipart encoding
1619
            logMetacat.debug("Disassembling MIME multipart form");
1620
            InputStream object = null;
1621
            InputStream sysmeta = null;
1622
            Map<String, List<String>> mutlipartparams;
1623
            
1624
            try
1625
            {
1626
                //String req = IOUtils.toString(request.getInputStream());
1627
                //System.out.println("request: " + req);
1628
                //InputStream reqStr = IOUtils.toInputStream(req);
1629
                InputStream reqStr = request.getInputStream();
1630
                
1631
                //handle MMP inputs
1632
                File tmpDir = getTempDirectory();
1633
                File tmpSMFile = new File(tmpDir + 
1634
                        ".sysmeta." + new Date().getTime() + ".tmp");
1635
                System.out.println("temp dir: " + tmpDir.getAbsolutePath());
1636
                MultipartRequestResolver mrr = new MultipartRequestResolver(
1637
                        tmpDir.getAbsolutePath(), 1000000000, 0);
1638
                MultipartRequest mr = mrr.resolveMultipart(request);
1639
                System.out.println("resolved multipart request");
1640
                Map<String, File> files = mr.getMultipartFiles();
1641
                if(files == null)
1642
                {
1643
                    throw new ServiceFailure("1202", "create/update must have multipart files with names 'object' and 'sysmeta'");
1644
                }
1645
                System.out.println("got multipart files");
1646
                
1647
                if(files.keySet() == null)
1648
                {
1649
                    System.out.println("No file keys in MMP request.");
1650
                    throw new ServiceFailure("1202", "No file keys found in MMP.  " +
1651
                            "create/update must have multipart files with names 'object' and 'sysmeta'");
1652
                }
1653
                Iterator multipartkeys = files.keySet().iterator();
1654
                System.out.println("iterating through multipart files: " + multipartkeys);
1655
                while(multipartkeys.hasNext())
1656
                {
1657
                    String key = (String)multipartkeys.next();
1658
                    System.out.println("files key: " + key);
1659
                    System.out.println("files value: " + files.get(key));
1660
                }
1661
                
1662
                mutlipartparams = mr.getMultipartParameters();
1663
                multipartkeys = mutlipartparams.keySet().iterator();
1664
                while(multipartkeys.hasNext())
1665
                {
1666
                    String key = (String)multipartkeys.next();
1667
                    System.out.println("mutlipartparams key: " + key);
1668
                    System.out.println("mutlipartparams value: " + mutlipartparams.get(key));
1669
                }
1670
                
1671
                Iterator keys = params.keySet().iterator();
1672
                while(keys.hasNext())
1673
                {
1674
                    String key = (String)keys.next();
1675
                    System.out.println("param key: " + key);
1676
                    System.out.println("param value: " + params.get(key));
1677
                }
1678
                
1679
                File smFile = files.get("sysmeta");
1680
                System.out.println("smFile: " + smFile.getAbsolutePath());
1681
                sysmeta = new FileInputStream(smFile);
1682
                File objFile = files.get("object");
1683
                System.out.println("objectfile: " + objFile.getAbsolutePath());
1684
                object = new FileInputStream(objFile);
1685
                
1686
                /*String obj = IOUtils.toString(object);
1687
                String sm = IOUtils.toString(sysmeta);
1688
                System.out.println("object: " + obj);
1689
                System.out.println("sm: " + sm);
1690
                object = IOUtils.toInputStream(obj);
1691
                sysmeta = IOUtils.toInputStream(sm);*/
1692
                
1693
            }
1694
            catch(org.apache.commons.fileupload.FileUploadException fue)
1695
            {
1696
                throw new ServiceFailure("1202", "Could not upload MMP files: " + fue.getMessage());
1697
            }
1698
            catch(IOException ioe)
1699
            {
1700
                throw new ServiceFailure("1202", 
1701
                        "IOException when processing Mime Multipart: " + ioe.getMessage());
1702
            }
1703
            catch(Exception e)
1704
            {
1705
                throw new ServiceFailure("1202", "Error handling MMP upload: " + e.getMessage());
1706
            }
1707
            
1708
            if ( action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
1709

    
1710
                // Check if the objectId exists
1711
                IdentifierManager im = IdentifierManager.getInstance();
1712
                if (im.identifierExists(guid)) {
1713
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + guid);
1714
                }
1715

    
1716
                logMetacat.debug("Commence creation...");
1717
                IBindingFactory bfact =
1718
                    BindingDirectory.getFactory(SystemMetadata.class);
1719
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1720
                SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1721

    
1722
                CrudService cs = CrudService.getInstance();
1723
                AuthToken token = new AuthToken(sessionId); 
1724
                cs.setParamsFromRequest(request);
1725
                Identifier id = new Identifier();
1726
                id.setValue(guid);
1727
                System.out.println("creating object with guid " + id.getValue());
1728
                Identifier rId = cs.create(token, id, object, m);
1729
                serializeServiceType(Identifier.class, rId, out);
1730
                
1731
            } else if (action.equals(FUNCTION_NAME_UPDATE)) { //handle updates
1732
                IdentifierManager im = IdentifierManager.getInstance();
1733
                CrudService cs = CrudService.getInstance();
1734
                Identifier obsoletedGuid = new Identifier();
1735
                Identifier id = new Identifier();
1736
                id.setValue(guid);
1737
                AuthToken token = new AuthToken(sessionId);
1738
                
1739
                //do some checks
1740
                if(mutlipartparams.get("obsoletedGuid") == null)
1741
                {
1742
                    throw new InvalidRequest("1202", "obsoletedGuid must be contained in the request parameters.");
1743
                }
1744
                //get the obsoletedGuid
1745
                String obsGuidS = mutlipartparams.get("obsoletedGuid").get(0);
1746
                obsoletedGuid.setValue(obsGuidS);
1747
                
1748
                if (!im.identifierExists(obsoletedGuid.getValue())) 
1749
                {
1750
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1751
                }
1752
                
1753
                
1754
                logMetacat.debug("Commence update...");
1755
                
1756
                //get the systemmetadata
1757
                IBindingFactory bfact =
1758
                        BindingDirectory.getFactory(SystemMetadata.class);
1759
                    IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1760
                    SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1761
                
1762
                //do the update
1763
                try
1764
                {
1765
                    cs.setParamsFromRequest(request);
1766
                    Identifier rId = cs.update(token, id, object, obsoletedGuid, m);
1767
                    serializeServiceType(Identifier.class, rId, out);
1768
                }
1769
                catch(NotFound e)
1770
                {
1771
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1772
                }
1773
                
1774
            } else {
1775
                throw new InvalidRequest("1000", "Operation must be create or update.");
1776
            }
1777
            
1778
            //clean up the MMP files
1779
            //parts.get("systemmetadata").delete();
1780
            //parts.get("object").delete();
1781
        } catch (NotAuthorized e) {
1782
            response.setStatus(500);
1783
            serializeException(e, out);
1784
        } catch (InvalidToken e) {
1785
            response.setStatus(500);
1786
            serializeException(e, out);
1787
        } catch (ServiceFailure e) {
1788
            response.setStatus(500);
1789
            serializeException(e, out);
1790
        } catch (IdentifierNotUnique e) {
1791
            response.setStatus(500);
1792
            serializeException(e, out);
1793
        } catch (UnsupportedType e) {
1794
            response.setStatus(500);
1795
            serializeException(e, out);
1796
        } catch (InsufficientResources e) {
1797
            response.setStatus(500);
1798
            serializeException(e, out);
1799
        } catch (InvalidSystemMetadata e) {
1800
            response.setStatus(500);
1801
            serializeException(e, out);
1802
        } catch (NotImplemented e) {
1803
            response.setStatus(500);
1804
            serializeException(e, out);
1805
        } catch (InvalidRequest e) {
1806
            response.setStatus(500);
1807
            serializeException(e, out);
1808
        } /*catch (MessagingException e) {
1809
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1810
            serializeException(sf, out);
1811
        } catch (IOException e) {
1812
            response.setStatus(500);
1813
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1814
            serializeException(sf, out);
1815
        }*/ catch (JiBXException e) {
1816
            response.setStatus(500);
1817
            e.printStackTrace(System.out);
1818
            InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e.getMessage());
1819
            serializeException(ism, out);
1820
        }
1821
    }
1822

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

    
1914
    /**
1915
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
1916
     * 
1917
     * @throws IOException
1918
     */
1919
    private void login() throws IOException {
1920
        PrintWriter out = response.getWriter();
1921
        response.setStatus(200);
1922
        response.setContentType("text/xml");
1923
        handler.handleLoginAction(out, params, request, response);
1924
        out.close();
1925
    }
1926

    
1927
    /**
1928
     * Earthgrid API > Authentication Service > Logout Function : calls MetacatHandler > handleLogoutAction
1929
     * 
1930
     * @throws IOException
1931
     */
1932
    private void logout() throws IOException {
1933
        PrintWriter out = response.getWriter();
1934
        response.setStatus(200);
1935
        response.setContentType("text/xml");
1936
        handler.handleLogoutAction(out, params, request, response);
1937
        out.close();
1938
    }
1939

    
1940
    /**
1941
     * Prints xml response
1942
     * @param message Message to be displayed
1943
     * @param response Servlet response that xml message will be printed 
1944
     * */
1945
    private void printError(String message, HttpServletResponse response) {
1946
        try {
1947
            logMetacat.error("ResourceHandler: Printing error to servlet response: " + message);
1948
            PrintWriter out = response.getWriter();
1949
            response.setContentType("text/xml");
1950
            out.println("<?xml version=\"1.0\"?>");
1951
            out.println("<error>");
1952
            out.println(message);
1953
            out.println("</error>");
1954
            out.close();
1955
        } catch (IOException e) {
1956
            e.printStackTrace();
1957
        }
1958
    }
1959
    
1960
    /**
1961
     * serialize a D1 exception using jibx
1962
     * @param e
1963
     * @param out
1964
     */
1965
    private void serializeException(BaseException e, OutputStream out) {
1966
        // TODO: Use content negotiation to determine which return format to use
1967
        response.setContentType("text/xml");
1968
        response.setStatus(e.getCode());
1969
        
1970
        logMetacat.error("ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
1971
        e.printStackTrace();
1972
        
1973
        try {
1974
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
1975
        } catch (IOException e1) {
1976
            logMetacat.error("Error writing exception to stream. " 
1977
                    + e1.getMessage());
1978
        }
1979
    }
1980
    
1981
    /**
1982
     * create a new ServiceMethod declaration
1983
     * @param name
1984
     * @param rest
1985
     * @param implemented
1986
     * @return
1987
     */
1988
    private ServiceMethod getServiceMethod(String name, String rest, boolean implemented)
1989
    {
1990
        ServiceMethod sm = new ServiceMethod();
1991
        sm.setImplemented(implemented);
1992
        sm.setName(name);
1993
        sm.setRest(rest);
1994
        return sm;
1995
    }
1996

    
1997
}
(4-4/5)