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.client.ObjectFormatCache;
49
import org.dataone.mimemultipart.MultipartRequest;
50
import org.dataone.mimemultipart.MultipartRequestResolver;
51
import org.dataone.service.NodeListParser;
52
import org.dataone.service.exceptions.BaseException;
53
import org.dataone.service.exceptions.IdentifierNotUnique;
54
import org.dataone.service.exceptions.InsufficientResources;
55
import org.dataone.service.exceptions.InvalidRequest;
56
import org.dataone.service.exceptions.InvalidSystemMetadata;
57
import org.dataone.service.exceptions.InvalidToken;
58
import org.dataone.service.exceptions.NotAuthorized;
59
import org.dataone.service.exceptions.NotImplemented;
60
import org.dataone.service.exceptions.ServiceFailure;
61
import org.dataone.service.exceptions.UnsupportedType;
62
import org.dataone.service.exceptions.NotFound;
63
import org.dataone.service.types.*;
64
import org.dataone.service.types.util.ServiceTypeUtil;
65
import org.jibx.runtime.BindingDirectory;
66
import org.jibx.runtime.IBindingFactory;
67
import org.jibx.runtime.IMarshallingContext;
68
import org.jibx.runtime.IUnmarshallingContext;
69
import org.jibx.runtime.JiBXException;
70

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
305
                if(resource.equals(RESOURCE_BASE_URL)) {
306
                    //node registry response
307
                    System.out.println("Using resource 'd1' (node registry response)");
308
                    createNodeResponse();
309
                    status = true;
310
                    
311
                } else if (resource.equals(RESOURCE_SESSION) && 
312
                        httpVerb == POST && 
313
                        params.get(FUNCTION_KEYWORD) != null) {
314
                    System.out.println("Using resource 'session'");
315
                    //System.out.println("function_keyword: " + params.get(FUNCTION_KEYWORD)[0]);
316
                    if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGIN)) {
317
                        login();
318
                        status = true;
319
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGOUT)) {
320
                        logout();
321
                        status = true;
322
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_SET_ACCESS)) {
323
                        setaccess();
324
                        status = true;
325
                        System.out.println("done setting access");
326
                    }
327
                } else if (resource.equals(RESOURCE_META)) {
328
                    System.out.println("Using resource 'meta'");
329
                    if (params != null && params.get(FUNCTION_KEYWORD) != null &&
330
                            params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA))
331
                    { 
332
                        status = true;
333
                    }
334
                    else
335
                    {
336
                        String objectId = request.getPathInfo();
337
                        if (objectId != null && objectId.length() > 1) 
338
                        {
339
                            objectId = request.getPathInfo().substring(1);
340
                        }
341
                        
342
                        // get
343
                        if (httpVerb == GET) {
344
	                        getSystemMetadataObject(objectId);
345
	                        status = true;
346
                        }
347
                        
348
                        // post to register system metadata
349
                        if (httpVerb == POST) {
350
                        	registerSystemMetadata(objectId);
351
                        	status = true;
352
                        }
353
                        
354
                    }
355

    
356
                } else if (resource.equals(RESOURCE_OBJECTS)) {
357
                    System.out.println("Using resource 'object'");
358
                    logMetacat.debug("D1 Rest: Starting resource processing...");
359
                    loadSessionData();
360

    
361
                    String objectId = request.getPathInfo();
362
                    if (objectId != null && objectId.length() > 1) 
363
                    {
364
                        objectId = request.getPathInfo().substring(1);
365
                    }
366
                    else
367
                    {
368
                        objectId = null;
369
                    }
370
                    
371
                    System.out.println("objectId in ReasourceHandler.handle: " + objectId);
372

    
373
                    logMetacat.debug("verb:" + httpVerb);
374

    
375
                    if (httpVerb == GET) {
376
                        getObject(objectId);
377
                        status = true;
378
                    } else if (httpVerb == POST) {
379
                        putObject(objectId, FUNCTION_NAME_INSERT);
380
                        status = true;
381
                    } else if (httpVerb == PUT) {
382
                        putObject(objectId, FUNCTION_NAME_UPDATE);
383
                        status = true;
384
                    } else if (httpVerb == DELETE) {
385
                        deleteObject(objectId);
386
                        status = true;
387
                    } else if (httpVerb == HEAD) {
388
                        describeObject(objectId);
389
                        status = true;
390
                    }
391
                    
392

    
393
                } else if (resource.equals(RESOURCE_IDENTIFIER)) {
394
                    System.out.println("Using resource 'identifier'");
395
                    String identifierId = request.getPathInfo();
396
                    if (identifierId != null && identifierId.length() > 1)
397
                        identifierId = request.getPathInfo().substring(1); //trim the slash
398

    
399
                    if (httpVerb == GET) {
400
                        String op = params.get(FUNCTION_KEYWORD)[0];
401
                        if (op.equals(FUNCTION_NAME_ISREGISTERED)) {
402
                            isRegistered(identifierId);
403
                            status = true;
404
                        } else if (op.equals(FUNCTION_NAME_GETALLDOCS)) {
405
                            getAllDocIds();
406
                            status = true;
407
                        } else if (op.equals(FUNCTION_NAME_GETNEXTREV)) {
408
                            getNextRevision(identifierId);
409
                            status = true;
410
                        } else if (op.equals(FUNCTION_NAME_GETNEXTOBJ)) {
411
                            getNextObject();
412
                            status = true;
413
                        } 
414

    
415
                    } else if (httpVerb == PUT) {
416
                        //Earthgrid API > Identifier Service > addLSID Function 
417
                        response.setStatus(501);
418
                        printError(
419
                                "This method is not supported by metacat.  To "
420
                                + "add a new LSID, add a document to metacat.",
421
                                response);
422
                        status = true;
423
                    }
424

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

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

    
965
        String name = null;
966
        String[] value = null;
967
        Enumeration paramlist = request.getParameterNames();
968
        while (paramlist.hasMoreElements()) {
969
            name = (String) paramlist.nextElement();
970
            value = request.getParameterValues(name);
971
            params.put(name, value);
972
        }
973
    }
974

    
975
    /**
976
     * 
977
     * Load user details of metacat session from the request 
978
     * 
979
     */
980
    private void loadSessionData()
981
      throws Exception
982
    {
983
        SessionData sessionData = RequestUtil.getSessionData(request);
984
        try
985
        {
986
            username = null;
987
            password = null;
988
            groupNames = null;
989
            sessionId = null;
990
            
991
            boolean validSession = false;
992
            SessionService ss = SessionService.getInstance();
993
            System.out.println("sessionData: " + sessionData);
994
            if(sessionData == null)
995
            {
996
                username = "public";
997
                sessionId = "0";
998
                System.out.println("sessiondata is null.  Creating a public session.");
999
                return;
1000
            }
1001
            
1002
            System.out.println("username: " + sessionData.getUserName());
1003
            System.out.println("sessionid: " + sessionData.getId());
1004
            //validate the session
1005
            if(ss.isSessionRegistered(sessionData.getId()) && 
1006
               !(sessionData.getUserName().equals("public") || sessionData.getId().equals("0")))
1007
            {
1008
                validSession = true;
1009
            }
1010
            
1011
            if(validSession)
1012
            {
1013
                //if the session is valid, set these variables
1014
                username = sessionData.getUserName();
1015
                password = sessionData.getPassword();
1016
                groupNames = sessionData.getGroupNames();
1017
                sessionId = sessionData.getId();
1018
                System.out.println("setting sessionid to " + sessionId);
1019
                System.out.println("username: " + username);
1020
            }
1021
            
1022
            //if the session is not valid or the username is null, set
1023
            //username to public
1024
            if (username == null) 
1025
            {
1026
                System.out.println("setting username to public.");
1027
                username = "public";
1028
            }
1029
        }
1030
        catch(Exception e)
1031
        {
1032
            e.printStackTrace();
1033
            throw new Exception("Could not load the session data: " + e.getClass() + ": " + e.getMessage());
1034
        }
1035
    }
1036

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

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

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

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

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

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

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

    
1126
        out.close();
1127
    }
1128

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

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

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

    
1460
            DBQuery metacat = new DBQuery();
1461

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

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

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

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

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

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

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

    
1657
		// for logging purposes, dump out the key-value pairs that constitute the request
1658
		// 3 types exist: request params, multipart params, and multipart files
1659
                Iterator it = files.keySet().iterator();
1660
                System.out.println("iterating through request parts: " + it);
1661
                while(it.hasNext())
1662
                {
1663
                    String key = (String)it.next();
1664
                    System.out.println("files key: " + key);
1665
                    System.out.println("files value: " + files.get(key));
1666
                }
1667
                
1668
                multipartparams = mr.getMultipartParameters();
1669
                it = multipartparams.keySet().iterator();
1670
                while(it.hasNext())
1671
                {
1672
                    String key = (String)it.next();
1673
                    System.out.println("multipartparams key: " + key);
1674
                    System.out.println("multipartparams value: " + multipartparams.get(key));
1675
                }
1676
                
1677
                it = params.keySet().iterator();
1678
                while(it.hasNext())
1679
                {
1680
                    String key = (String)it.next();
1681
                    System.out.println("param key: " + key);
1682
                    System.out.println("param value: " + params.get(key));
1683
                }
1684
		System.out.println("done iterating the request...");
1685

    
1686
                File smFile = files.get("sysmeta");
1687
		if (smFile == null) 
1688
		    throw new InvalidRequest("1102", "Missing the required file-part 'sysmeta' from the multipart request.");
1689
                System.out.println("smFile: " + smFile.getAbsolutePath());
1690
                sysmeta = new FileInputStream(smFile);
1691
                File objFile = files.get("object");
1692
		if (objFile == null) 
1693
		    throw new InvalidRequest("1102", "Missing the required file-part 'object' from the multipart request.");
1694

    
1695
                System.out.println("objectfile: " + objFile.getAbsolutePath());
1696
                object = new FileInputStream(objFile);
1697
                
1698
                /*String obj = IOUtils.toString(object);
1699
                String sm = IOUtils.toString(sysmeta);
1700
                System.out.println("object: " + obj);
1701
                System.out.println("sm: " + sm);
1702
                object = IOUtils.toInputStream(obj);
1703
                sysmeta = IOUtils.toInputStream(sm);*/
1704
                
1705
            }
1706
            catch(org.apache.commons.fileupload.FileUploadException fue)
1707
            {
1708
                throw new ServiceFailure("1202", "Could not upload MMP files: " + fue.getMessage());
1709
            }
1710
            catch(IOException ioe)
1711
            {
1712
                throw new ServiceFailure("1202", 
1713
                        "IOException when processing Mime Multipart: " + ioe.getMessage());
1714
            }
1715
            catch(Exception e)
1716
            {
1717
                throw new ServiceFailure("1202", "Error handling MMP upload: " + e.getClass() + ": " + e.getMessage());
1718
            }
1719
            
1720
            if ( action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
1721

    
1722
                // Check if the objectId exists
1723
                IdentifierManager im = IdentifierManager.getInstance();
1724
                if (im.identifierExists(pid)) {
1725
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + pid);
1726
                }
1727

    
1728
                logMetacat.debug("Commence creation...");
1729
                IBindingFactory bfact =
1730
                    BindingDirectory.getFactory(SystemMetadata.class);
1731
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1732
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1733

    
1734
                CrudService cs = CrudService.getInstance();
1735
                AuthToken token = new AuthToken(sessionId); 
1736
                cs.setParamsFromRequest(request);
1737
                Identifier id = new Identifier();
1738
                id.setValue(pid);
1739
                System.out.println("creating object with pid " + id.getValue());
1740
                Identifier rId = cs.create(token, id, object, smd);
1741
                serializeServiceType(Identifier.class, rId, out);
1742
                
1743
            } else if (action.equals(FUNCTION_NAME_UPDATE)) { //handle updates
1744

    
1745
            	// Check if the objectId exists
1746
                IdentifierManager im = IdentifierManager.getInstance();
1747
                if (!im.identifierExists(pid)) {
1748
                    throw new NotFound("1280", "The pid you are trying to update does not exist: " + pid);
1749
                }
1750
                // check that the newPid parameter was provided and it doesn't exist
1751
                if(multipartparams.get("newPid") == null)
1752
                    throw new InvalidRequest("1202", "'newPid' must be contained in the request parameters.");
1753
                String newPidString = multipartparams.get("newPid").get(0);
1754
                if (im.identifierExists(newPidString)) 
1755
                    throw new IdentifierNotUnique("1220", "Identifier is already in use: " + newPidString);
1756
               
1757
                
1758
                Identifier newPid = new Identifier();
1759
                Identifier obsoletedPid = new Identifier();
1760
                newPid.setValue(newPidString);
1761
                obsoletedPid.setValue(pid);
1762
               
1763
            	
1764
                CrudService cs = CrudService.getInstance();
1765
                AuthToken token = new AuthToken(sessionId);
1766

    
1767
                logMetacat.debug("Commence update...");
1768
                
1769
                //get the systemmetadata
1770
                IBindingFactory bfact =
1771
                	BindingDirectory.getFactory(SystemMetadata.class);
1772
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1773
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1774

    
1775
                cs.setParamsFromRequest(request);
1776
                Identifier rId = cs.update(token, newPid, object, obsoletedPid, smd);
1777
                serializeServiceType(Identifier.class, rId, out);
1778
            } else {
1779
                throw new InvalidRequest("1000", "Operation must be create or update.");
1780
            }
1781
            
1782
            //clean up the MMP files
1783
            //parts.get("systemmetadata").delete();
1784
            //parts.get("object").delete();
1785
        } catch (NotAuthorized e) {
1786
            response.setStatus(500);
1787
            serializeException(e, out);
1788
        } catch (InvalidToken e) {
1789
            response.setStatus(500);
1790
            serializeException(e, out);
1791
        } catch (ServiceFailure e) {
1792
            response.setStatus(500);
1793
            serializeException(e, out);
1794
        } catch (NotFound e) {
1795
            response.setStatus(500);
1796
            serializeException(e, out);
1797
        } catch (IdentifierNotUnique e) {
1798
            response.setStatus(500);
1799
            serializeException(e, out);
1800
        } catch (UnsupportedType e) {
1801
            response.setStatus(500);
1802
            serializeException(e, out);
1803
        } catch (InsufficientResources e) {
1804
            response.setStatus(500);
1805
            serializeException(e, out);
1806
        } catch (InvalidSystemMetadata e) {
1807
            response.setStatus(500);
1808
            serializeException(e, out);
1809
        } catch (NotImplemented e) {
1810
            response.setStatus(500);
1811
            serializeException(e, out);
1812
        } catch (InvalidRequest e) {
1813
            response.setStatus(500);
1814
            serializeException(e, out);
1815
        } /*catch (MessagingException e) {
1816
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1817
            serializeException(sf, out);
1818
        } catch (IOException e) {
1819
            response.setStatus(500);
1820
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1821
            serializeException(sf, out);
1822
        }*/ catch (JiBXException e) {
1823
            response.setStatus(500);
1824
            e.printStackTrace(System.out);
1825
            InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e.getMessage());
1826
            serializeException(ism, out);
1827
        }
1828
    }
1829

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

    
1921
    /**
1922
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
1923
     * 
1924
     * @throws IOException
1925
     */
1926
    private void login() throws IOException {
1927
        PrintWriter out = response.getWriter();
1928
        response.setStatus(200);
1929
        response.setContentType("text/xml");
1930
        handler.handleLoginAction(out, params, request, response);
1931
        out.close();
1932
    }
1933

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

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

    
2004
    /**
2005
     * Register System Metadata without data or metadata object
2006
     * @param pid identifier for System Metadata entry
2007
     */
2008
	private void registerSystemMetadata(String pid) {
2009
		logMetacat.debug("Entering registerSystemMetadata: " + pid);
2010
		OutputStream out = null;
2011
		try {
2012
			out = response.getOutputStream();
2013
			response.setStatus(200);
2014
			response.setContentType("text/xml");
2015
		} catch (IOException e1) {
2016
			logMetacat.error("Could not get the output stream for writing in putObject");
2017
		}
2018
		try {
2019

    
2020
			// Read the incoming data from its Mime Multipart encoding
2021
			logMetacat.debug("Disassembling MIME multipart form");
2022
			InputStream sysmeta = null;
2023
			Map<String, List<String>> multipartparams;
2024

    
2025
			try {
2026

    
2027
				// handle MMP inputs
2028
				File tmpDir = getTempDirectory();
2029

    
2030
				logMetacat.debug("temp dir: " + tmpDir.getAbsolutePath());
2031
				MultipartRequestResolver mrr = new MultipartRequestResolver(
2032
						tmpDir.getAbsolutePath(), 1000000000, 0);
2033
				MultipartRequest mr = mrr.resolveMultipart(request);
2034
				logMetacat.debug("resolved multipart request");
2035
				Map<String, File> files = mr.getMultipartFiles();
2036
				if (files == null) {
2037
					throw new ServiceFailure("1202",
2038
							"register meta must have multipart file with name 'sysmeta'");
2039
				}
2040
				logMetacat.debug("got multipart files");
2041

    
2042
				if (files.keySet() == null) {
2043
					logMetacat.error("No file keys in MMP request.");
2044
					throw new ServiceFailure(
2045
							"1202",
2046
							"No file keys found in MMP.  "
2047
									+ "register meta must have multipart file with name 'sysmeta'");
2048
				}
2049

    
2050
				// for logging purposes, dump out the key-value pairs that
2051
				// constitute the request
2052
				// 3 types exist: request params, multipart params, and
2053
				// multipart files
2054
				Iterator it = files.keySet().iterator();
2055
				logMetacat.debug("iterating through request parts: " + it);
2056
				while (it.hasNext()) {
2057
					String key = (String) it.next();
2058
					logMetacat.debug("files key: " + key);
2059
					logMetacat.debug("files value: " + files.get(key));
2060
				}
2061

    
2062
				multipartparams = mr.getMultipartParameters();
2063
				it = multipartparams.keySet().iterator();
2064
				while (it.hasNext()) {
2065
					String key = (String) it.next();
2066
					logMetacat.debug("multipartparams key: " + key);
2067
					logMetacat.debug("multipartparams value: "
2068
							+ multipartparams.get(key));
2069
				}
2070

    
2071
				it = params.keySet().iterator();
2072
				while (it.hasNext()) {
2073
					String key = (String) it.next();
2074
					logMetacat.debug("param key: " + key);
2075
					logMetacat.debug("param value: " + params.get(key));
2076
				}
2077
				logMetacat.debug("done iterating the request...");
2078

    
2079
				File smFile = files.get("sysmeta");
2080
				if (smFile == null) {
2081
					throw new InvalidRequest("1102",
2082
							"Missing the required file-part 'sysmeta' from the multipart request.");
2083
				}
2084
				logMetacat.debug("smFile: " + smFile.getAbsolutePath());
2085
				sysmeta = new FileInputStream(smFile);
2086

    
2087
			} catch (org.apache.commons.fileupload.FileUploadException fue) {
2088
				throw new ServiceFailure("1202", "Could not upload MMP files: "
2089
						+ fue.getMessage());
2090
			} catch (IOException ioe) {
2091
				throw new ServiceFailure("1202",
2092
						"IOException when processing Mime Multipart: "
2093
								+ ioe.getMessage());
2094
			} catch (Exception e) {
2095
				throw new ServiceFailure("1202", "Error handling MMP upload: "
2096
						+ e.getClass() + ": " + e.getMessage());
2097
			}
2098

    
2099
			// Check if the objectId exists
2100
			IdentifierManager im = IdentifierManager.getInstance();
2101
			if (im.identifierExists(pid)) {
2102
				throw new IdentifierNotUnique("1000",
2103
						"Identifier is already in use: " + pid);
2104
			}
2105

    
2106
			logMetacat.debug("Commence creation...");
2107
			IBindingFactory bfact = BindingDirectory
2108
					.getFactory(SystemMetadata.class);
2109
			IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
2110
			SystemMetadata systemMetadata = (SystemMetadata) uctx
2111
					.unmarshalDocument(sysmeta, null);
2112

    
2113
			// TODO: get session
2114
			Session session = null;
2115
			Identifier guid = new Identifier();
2116
			guid.setValue(pid);
2117
			logMetacat.debug("registering system metadata with pid "
2118
					+ guid.getValue());
2119
			boolean result = CNCoreImpl.getInstance().registerSystemMetaData(
2120
					session, guid, systemMetadata);
2121
			serializeServiceType(Boolean.class, result, out);
2122

    
2123
		} catch (NotAuthorized e) {
2124
			response.setStatus(500);
2125
			serializeException(e, out);
2126
		} catch (ServiceFailure e) {
2127
			response.setStatus(500);
2128
			serializeException(e, out);
2129
		} catch (IdentifierNotUnique e) {
2130
			response.setStatus(500);
2131
			serializeException(e, out);
2132
		} catch (NotImplemented e) {
2133
			response.setStatus(500);
2134
			serializeException(e, out);
2135
		} catch (InvalidRequest e) {
2136
			response.setStatus(500);
2137
			serializeException(e, out);
2138
		} catch (JiBXException e) {
2139
			response.setStatus(500);
2140
			e.printStackTrace(System.out);
2141
			InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e
2142
					.getMessage());
2143
			serializeException(ism, out);
2144
		}
2145
	}
2146

    
2147
}
(4-4/5)