Project

General

Profile

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

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

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

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

    
43

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1125
        out.close();
1126
    }
1127

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

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

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

    
1456
            DBQuery metacat = new DBQuery();
1457

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

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

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

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

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

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

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

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

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

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

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

    
1724
                logMetacat.debug("Commence creation...");
1725
                IBindingFactory bfact =
1726
                    BindingDirectory.getFactory(SystemMetadata.class);
1727
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1728
                SystemMetadata smd = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1729

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

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

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

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

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

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

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

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

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

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

    
2021
			try {
2022

    
2023
				// handle MMP inputs
2024
				File tmpDir = getTempDirectory();
2025

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

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

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

    
2058
				multipartparams = mr.getMultipartParameters();
2059
				it = multipartparams.keySet().iterator();
2060
				while (it.hasNext()) {
2061
					String key = (String) it.next();
2062
					logMetacat.debug("multipartparams key: " + key);
2063
					logMetacat.debug("multipartparams value: "
2064
							+ multipartparams.get(key));
2065
				}
2066

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

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

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

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

    
2102
			logMetacat.debug("Commence creation...");
2103
			IBindingFactory bfact = BindingDirectory
2104
					.getFactory(SystemMetadata.class);
2105
			IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
2106
			SystemMetadata systemMetadata = (SystemMetadata) uctx
2107
					.unmarshalDocument(sysmeta, null);
2108

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

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

    
2143
}
(4-4/5)