Project

General

Profile

1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2011 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: Serhan AKIN $'
7
 *     '$Date: 2009-06-13 15:28:13 +0300  $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.restservice;
24

    
25
import java.io.*;
26
import java.net.URL;
27
import java.util.*;
28

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

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

    
43

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1145
        out.close();
1146
    }
1147

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

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

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

    
1480
            DBQuery metacat = new DBQuery();
1481

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

    
1488
            // parameter: queryspecification, user, group, usingIndexOrNot
1489
            StringBuffer result = metacat.createResultDocument(xmlquery,
1490
                    metacatQuery, out, username, groupNames, useXMLIndex);
1491

    
1492
            // create result set transfer       
1493
            String saxparser = PropertyService.getProperty("xml.saxparser");
1494
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
1495
                    new StringReader(result.toString()), saxparser, queryType
1496
                            .getNamespace().get_value());
1497
            ResultsetType records = metacatResultsetParser.getEcogridResult();
1498

    
1499
            System.out
1500
                    .println(EcogridResultsetTransformer.toXMLString(records));
1501
            response.setContentType("text/xml");
1502
            out = response.getWriter();
1503
            out.print(EcogridResultsetTransformer.toXMLString(records));
1504

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

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

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

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

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

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

    
1742
                // Check if the objectId exists
1743
                IdentifierManager im = IdentifierManager.getInstance();
1744
                if (im.identifierExists(pid)) {
1745
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + pid);
1746
                }
1747

    
1748
                logMetacat.debug("Commence creation...");
1749
                IBindingFactory bfact =
1750
                    BindingDirectory.getFactory(SystemMetadata.class);
1751
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1752
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1753

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

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

    
1787
                logMetacat.debug("Commence update...");
1788
                
1789
                //get the systemmetadata
1790
                IBindingFactory bfact =
1791
                	BindingDirectory.getFactory(SystemMetadata.class);
1792
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1793
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1794

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

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

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

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

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

    
2024
}
(4-4/5)