Project

General

Profile

1 5211 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 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 5370 berkley
import java.io.*;
26
import java.util.*;
27 5211 jones
28 5319 jones
import javax.mail.BodyPart;
29
import javax.mail.MessagingException;
30
import javax.mail.internet.MimeMultipart;
31 5211 jones
import javax.servlet.ServletContext;
32
import javax.servlet.http.HttpServletRequest;
33
import javax.servlet.http.HttpServletResponse;
34 5370 berkley
import java.text.DateFormat;
35 5428 berkley
import java.text.ParseException;
36 5391 berkley
import java.text.ParsePosition;
37
import java.text.SimpleDateFormat;
38 5211 jones
39 5391 berkley
40 5390 berkley
import org.apache.commons.httpclient.util.DateParser;
41 5299 jones
import org.apache.commons.io.IOUtils;
42 5211 jones
import org.apache.log4j.Logger;
43 5629 berkley
import org.apache.maven.artifact.ant.shaded.IOUtil;
44 5299 jones
import org.dataone.service.exceptions.BaseException;
45 5319 jones
import org.dataone.service.exceptions.IdentifierNotUnique;
46
import org.dataone.service.exceptions.InsufficientResources;
47
import org.dataone.service.exceptions.InvalidRequest;
48
import org.dataone.service.exceptions.InvalidSystemMetadata;
49
import org.dataone.service.exceptions.InvalidToken;
50
import org.dataone.service.exceptions.NotAuthorized;
51
import org.dataone.service.exceptions.NotImplemented;
52 5299 jones
import org.dataone.service.exceptions.ServiceFailure;
53 5319 jones
import org.dataone.service.exceptions.UnsupportedType;
54 5353 berkley
import org.dataone.service.exceptions.NotFound;
55 5370 berkley
import org.dataone.service.types.*;
56 5320 jones
import org.jibx.runtime.BindingDirectory;
57
import org.jibx.runtime.IBindingFactory;
58 5332 jones
import org.jibx.runtime.IMarshallingContext;
59 5320 jones
import org.jibx.runtime.IUnmarshallingContext;
60
import org.jibx.runtime.JiBXException;
61 5211 jones
62
import edu.ucsb.nceas.metacat.DBUtil;
63 5282 jones
import edu.ucsb.nceas.metacat.IdentifierManager;
64
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
65 5760 leinfelder
import edu.ucsb.nceas.metacat.MetaCatServlet;
66 5211 jones
import edu.ucsb.nceas.metacat.MetacatHandler;
67 5425 berkley
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
68 5299 jones
import edu.ucsb.nceas.metacat.dataone.CrudService;
69 5763 berkley
import edu.ucsb.nceas.metacat.dataone.HealthService;
70 5637 berkley
import edu.ucsb.nceas.metacat.properties.PropertyService;
71 5374 berkley
import edu.ucsb.nceas.metacat.service.SessionService;
72 5211 jones
import edu.ucsb.nceas.metacat.util.RequestUtil;
73
import edu.ucsb.nceas.metacat.util.SessionData;
74 5637 berkley
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
75
76 5629 berkley
import org.dataone.service.streaming.util.StreamUtil;
77 5636 berkley
78
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
79 5211 jones
/**
80
 *
81
 * Implements Earthgrid REST API to Metacat <br/><br/>
82
 *
83
 * <ul>
84
 * <li>
85
 * <h3> EarthGrid Query Service</h3>
86
 * <ul><li>
87
 * <h3>Get & Authenticated Get:</h3>
88
 * is equal to Metacat's read action and returns a data file having
89
 * the specified <doc-id> in the resource path. For authenticated Get service, a session id must be provided
90
 * in the query string. <br/><br/>
91
 *
92 5657 berkley
 * <b>REST URL:</b> <code>GET, [context-root]/object/[doc-id]?sessionid=[sessionid] </code><br/>
93 5211 jones
 * <b>Returns:</b> data file <br/><br/>
94
 * </li>
95
 *
96
 * <li>
97
 * <h3>Query & Authenticated Query:</h3>
98
 * Metacat's equivalent is squery action but this function
99
 * receives a Earthgrid query document and returns Earthgrid resultset document by transforming those documents
100
 * to Metacat's equivalents by the means of Metacat Implementation in Earthgrid library. For authenticated Query service
101
 * a session id must be provided in the query string. See Earthgrid (a.k.a. Ecogrid) project for XSD files of
102
 * query and resultset documents<br/><br/>
103
 *
104 5657 berkley
 * <b>REST URL:</b> <code>POST, [context-root]/object?sessionid=[sessionid]</code>    <br/>
105 5211 jones
 * <b>POST Data:</b> Earthgrid query document , Content-type: <code>text/xml</code><br/>
106
 * <b>Returns:</b> Earthgrid resultset document<br/><br/>
107
 *
108
 * </li>
109
 * </ul>
110
 *
111
 * </li>
112
 *
113
 * <li>
114
 * <h3> EarthGrid Authentication Service</h3>
115
 * <ul><li>
116
 * <h3>Login: </h3>
117
 * Receives username and password parameters in POST data and
118
 * returns SessionId (in XML format) or failure message and uses MetacatHandler's handleLoginAction function<br/><br/>
119
 *
120
 * <b>REST URL:</b> <code>POST, [context-root]/session?op=login</code> <br/>
121
 * <b>POST Data:</b> username=[username]&password=[password], Content-type: <code>application/x-www-form-urlencoded</code>
122
 * <b>Returns:</b> sessionId in XML format<br/><br/>
123
 * </li>
124
 *
125
 * <li>
126
 * <h3>Logout: </h3>
127
 * Receives session Id parameters in querystring and returns xml message, calls
128
 * MetacatHandler's handleLogoutAction function<br/><br/>
129
 *
130 5657 berkley
 * <b>REST URL:</b> <code>GET, [context-root]/session?op=logout&sessionid=[sessionid]</code>   <br/>
131 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
132
 * </li>
133
 * </ul>
134
 *
135
 * <li>
136
 * <h3>EarthGrid Put Service</h3>
137
 *
138
 * <ul>
139 5657 berkley
 * <li><h3>Update/Insert: </h3>
140 5211 jones
 * <br/>
141 5657 berkley
 * <b>REST URL:</b> <code>PUT, [context-root]/object/[doc-id]?op={update|insert}&sessionid=[sessionid]</code>   <br/>
142 5211 jones
 * <b>POST Data:</b> document object, Content-type: <code>text/xml</code><br/>
143
 * <b>Returns:</b> message in XML format<br/><br/>
144
 * </li>
145
 *
146 5657 berkley
 * <li><h3>Delete: </h3>
147 5211 jones
 * <br/>
148 5657 berkley
 * <b>REST URL:</b> <code>DELETE, [context-root]/object/[doc-id]?sessionid=[sessionid]</code>   <br/>
149 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
150
 * </li>
151
152
 * </ul>
153
 * </li>
154
 *
155
 * <li>
156
 * <h3>EarthGrid Identifier Service</h3><br/>
157
 *
158
 * <ul>
159 5657 berkley
 * <li><h3>isRegistered: </h3>      <br/>
160
 * <b>REST URL:</b> <code>GET, [context-root]/identifier/[doc-id]?op=isregistered</code>   <br/>
161 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
162
 * </li>
163
164 5657 berkley
 * <li><h3>getAllDocIds:</h3>       <br/>
165
 * <b>REST URL:</b> <code>GET, [context-root]/identifier?op=getalldocids</code>   <br/>
166 5211 jones
 * <b>Returns:</b> document id list in XML format<br/><br/>
167
 * </li>
168
 *
169
 * <li><h3>addLSID Function:</h3>
170 5657 berkley
 * Metacat does not support this function       <br/>
171
 * <b>REST URL:</b> <code>PUT, [context-root]/identifier/[doc-id]</code>   <br/>
172 5211 jones
 * <b>Returns:</b> error message in XML format<br/><br/>
173
 * </li>
174
 *
175 5657 berkley
 * <li><h3>getNextRevision:</h3>        <br/>
176
 * <b>REST URL:</b> <code>GET, [context-root]/identifier/[doc-id]?op=getnextrevision</code>   <br/>
177 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
178
 * </li>
179
 *
180 5657 berkley
 * <li><h3>getNextObject:</h3>      <br/>
181
 * <b>REST URL:</b> <code>GET, [context-root]/identifier?op=getnextobject&scope=[scope]</code>   <br/>
182 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
183
 * </li>
184
 *
185
 * </li>
186
 * </ul>
187
 *
188
 */
189
public class ResourceHandler {
190
191
    /**HTTP Verb GET*/
192
    public static final byte GET = 1;
193
    /**HTTP Verb POST*/
194
    public static final byte POST = 2;
195
    /**HTTP Verb PUT*/
196
    public static final byte PUT = 3;
197
    /**HTTP Verb DELETE*/
198
    public static final byte DELETE = 4;
199 5651 berkley
    /**HTTP Verb HEAD*/
200
    public static final byte HEAD = 5;
201 5211 jones
202
    /*
203
     * API Resources
204
     */
205 5224 jones
    private static final String RESOURCE_OBJECTS = "object";
206 5355 berkley
    private static final String RESOURCE_META = "meta";
207 5211 jones
    private static final String RESOURCE_SESSION = "session";
208
    private static final String RESOURCE_IDENTIFIER = "identifier";
209 5390 berkley
    private static final String RESOURCE_LOG = "log";
210 5644 berkley
    private static final String RESOURCE_CHECKSUM = "checksum";
211 5763 berkley
    private static final String RESOURCE_MONITOR = "monitor";
212 5692 berkley
    private static final String RESOURCE_BASE_URL = "d1";
213 5211 jones
214
    /*
215
     * API Functions used as URL parameters
216
     */
217
    private static final String FUNCTION_KEYWORD = "op";
218
    private static final String FUNCTION_NAME_LOGIN = "login";
219
    private static final String FUNCTION_NAME_LOGOUT = "logout";
220 5370 berkley
    private static final String FUNCTION_NAME_SET_ACCESS = "setaccess";
221 5211 jones
    private static final String FUNCTION_NAME_ISREGISTERED = "isregistered";
222
    private static final String FUNCTION_NAME_GETALLDOCS = "getalldocids";
223
    private static final String FUNCTION_NAME_GETNEXTREV = "getnextrevision";
224
    private static final String FUNCTION_NAME_GETNEXTOBJ = "getnextobject";
225
    private static final String FUNCTION_NAME_INSERT = "insert";
226
    private static final String FUNCTION_NAME_UPDATE = "update";
227 5374 berkley
    private static final String FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA = "generatemissingsystemmetadata";
228 5211 jones
229 5652 berkley
    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
230 5414 berkley
231 5211 jones
    private ServletContext servletContext;
232
    private Logger logMetacat;
233
    private MetacatHandler handler;
234
    private HttpServletRequest request;
235
    private HttpServletResponse response;
236
    private String username;
237
    private String password;
238
    private String sessionId;
239
    private String[] groupNames;
240
241
    private Hashtable<String, String[]> params;
242
243
    /**Initializes new instance by setting servlet context,request and response*/
244
    public ResourceHandler(ServletContext servletContext,
245
            HttpServletRequest request, HttpServletResponse response) {
246
        this.servletContext = servletContext;
247
        this.request = request;
248
        this.response = response;
249
    }
250
251
    /**
252
     * This function is called from REST APU servlet and handles each request to the servlet
253
     *
254
     * @param httpVerb (GET, POST, PUT or DELETE)
255
     */
256
    public void handle(byte httpVerb) {
257
        logMetacat = Logger.getLogger(ResourceHandler.class);
258
        try {
259
            String resource = request.getServletPath();
260 5692 berkley
            if(resource.endsWith("d1/") || resource.endsWith("d1"))
261
            {
262
                resource = RESOURCE_BASE_URL;
263
            }
264
            else
265
            {
266
                //substring off the /d1/
267
                resource = resource.substring(resource.indexOf("d1/") + 3, resource.length());
268
                resource = resource.trim();
269
            }
270
271 5355 berkley
            String verb = "";
272 5370 berkley
273 5691 berkley
            System.out.println("handling verb " + httpVerb + " request with resource '" + resource + "'");
274 5763 berkley
            System.out.println("resource: '" + resource + "'");
275
            System.out.println("resource_monitor: '" + RESOURCE_MONITOR + "'");
276 5211 jones
            boolean status = false;
277 5424 berkley
            loadSessionData();
278 5211 jones
279
            if (resource != null) {
280 5691 berkley
                //resource = request.getServletPath().substring(1);
281 5211 jones
282 5657 berkley
                params = new Hashtable<String, String[]>();
283
                initParams();
284 5211 jones
285 5657 berkley
                Timer timer = new Timer();
286
                handler = new MetacatHandler(timer);
287 5211 jones
288 5692 berkley
                if(resource.equals(RESOURCE_BASE_URL)) {
289
                    //node registry response
290
                    System.out.println("Using resource 'd1' (node registry response)");
291
                    createNodeResponse();
292
                    status = true;
293
294
                } else if (resource.equals(RESOURCE_SESSION) &&
295 5657 berkley
                        httpVerb == POST &&
296
                        params.get(FUNCTION_KEYWORD) != null) {
297 5691 berkley
                    System.out.println("Using resource 'session'");
298 5657 berkley
                    //System.out.println("function_keyword: " + params.get(FUNCTION_KEYWORD)[0]);
299
                    if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGIN)) {
300
                        login();
301
                        status = true;
302
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGOUT)) {
303
                        logout();
304
                        status = true;
305
                    } else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_SET_ACCESS)) {
306
                        setaccess();
307
                        status = true;
308 5734 berkley
                        System.out.println("done setting access");
309 5657 berkley
                    }
310
                } else if (resource.equals(RESOURCE_META)) {
311 5691 berkley
                    System.out.println("Using resource 'meta'");
312 5657 berkley
                    if(params != null && params.get(FUNCTION_KEYWORD) != null &&
313
                            params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA))
314
                    { //generate system metadata for any object that is
315
                        //a) not system metadata itself
316
                        //b) does not already have a system metadata id in the systemmetadata table
317
                        //c) not a BIN object (data)
318
                        //TODO: check if we need this anymore.  Might be superceded
319
                        //by MetacatPopulator
320
                        generateMissingSystemMetadata();
321
                        status = true;
322
                    }
323
                    else
324
                    {
325
                        String objectId = request.getPathInfo();
326
                        if (objectId != null && objectId.length() > 1)
327
                        {
328
                            objectId = request.getPathInfo().substring(1);
329
                        }
330
                        getSystemMetadataObject(objectId);
331
                        status = true;
332
                    }
333 5211 jones
334 5657 berkley
                } else if (resource.equals(RESOURCE_OBJECTS)) {
335 5691 berkley
                    System.out.println("Using resource 'object'");
336 5657 berkley
                    logMetacat.debug("D1 Rest: Starting resource processing...");
337
                    loadSessionData();
338 5211 jones
339 5657 berkley
                    String objectId = request.getPathInfo();
340
                    if (objectId != null && objectId.length() > 1)
341
                    {
342
                        objectId = request.getPathInfo().substring(1);
343
                    }
344
                    else
345
                    {
346
                        objectId = null;
347
                    }
348 5750 berkley
349
                    System.out.println("objectId in ReasourceHandler.handle: " + objectId);
350 5211 jones
351 5657 berkley
                    logMetacat.debug("verb:" + httpVerb);
352 5211 jones
353 5657 berkley
                    if (httpVerb == GET) {
354
                        getObject(objectId);
355
                        status = true;
356
                    } else if (httpVerb == POST) {
357
                        putObject(objectId, FUNCTION_NAME_INSERT);
358
                        status = true;
359
                    } else if (httpVerb == PUT) {
360
                        putObject(objectId, FUNCTION_NAME_UPDATE);
361
                        status = true;
362
                    } else if (httpVerb == DELETE) {
363
                        deleteObject(objectId);
364
                        status = true;
365
                    } else if (httpVerb == HEAD) {
366
                        describeObject(objectId);
367
                        status = true;
368
                    }
369
370 5211 jones
371 5657 berkley
                } else if (resource.equals(RESOURCE_IDENTIFIER)) {
372 5691 berkley
                    System.out.println("Using resource 'identifier'");
373 5657 berkley
                    String identifierId = request.getPathInfo();
374
                    if (identifierId != null && identifierId.length() > 1)
375
                        identifierId = request.getPathInfo().substring(1); //trim the slash
376 5211 jones
377 5657 berkley
                    if (httpVerb == GET) {
378
                        String op = params.get(FUNCTION_KEYWORD)[0];
379
                        if (op.equals(FUNCTION_NAME_ISREGISTERED)) {
380
                            isRegistered(identifierId);
381
                            status = true;
382
                        } else if (op.equals(FUNCTION_NAME_GETALLDOCS)) {
383
                            getAllDocIds();
384
                            status = true;
385
                        } else if (op.equals(FUNCTION_NAME_GETNEXTREV)) {
386
                            getNextRevision(identifierId);
387
                            status = true;
388
                        } else if (op.equals(FUNCTION_NAME_GETNEXTOBJ)) {
389
                            getNextObject();
390
                            status = true;
391
                        }
392 5446 jones
393 5657 berkley
                    } else if (httpVerb == PUT) {
394
                        //Earthgrid API > Identifier Service > addLSID Function
395
                        response.setStatus(501);
396
                        printError(
397
                                "This method is not supported by metacat.  To "
398
                                + "add a new LSID, add a document to metacat.",
399
                                response);
400
                        status = true;
401
                    }
402 5446 jones
403 5657 berkley
                } else if (resource.equals(RESOURCE_LOG)) {
404 5691 berkley
                    System.out.println("Using resource 'log'");
405 5657 berkley
                    //handle log events
406
                    if(httpVerb == GET)
407
                    {
408
                        getLog();
409
                        status = true;
410
                    }
411
                    else
412
                    {
413
                        //change to D1 spec for specifying which http methods are allowed for a resource
414
                        response.setStatus(501);
415
                        printError("POST, PUT, DELETE is not supported for logs.", response);
416
                        status = true;
417
                    }
418 5446 jones
419 5657 berkley
                } else if(resource.equals(RESOURCE_CHECKSUM)) {
420 5691 berkley
                    System.out.println("Using resource 'checksum'");
421 5657 berkley
                    //handle checksum requests
422
                    if(httpVerb == GET)
423
                    {
424
                        String guid = null;
425
                        String checksumAlgorithm = "MD5";
426
427
                        try
428
                        {
429
                           guid = params.get("id")[0];
430
                        }
431
                        catch(Exception e)
432
                        {
433
                            throw new InvalidRequest("1402", "Incorrect parameters passed to getChecksum");
434
                        }
435
436
                        Identifier guidid = new Identifier();
437
                        guidid.setValue(guid);
438
                        AuthToken token = new AuthToken(sessionId);
439
                        try
440
                        {
441
                            checksumAlgorithm = params.get("checksumAlgorithm")[0];
442
                        }
443
                        catch(Exception e)
444
                        {
445
                            //do nothing.  default to MD5
446
                        }
447
                        System.out.println("getting checksum for object " + guid +
448
                                " with algorithm " + checksumAlgorithm);
449
                        try
450
                        {
451
                            Checksum c = CrudService.getInstance().getChecksum(token, guidid, checksumAlgorithm);
452
                            System.out.println("got checksum " + c.getValue());
453
                            response.setStatus(200);
454
                            System.out.println("serializing response");
455
                            serializeServiceType(Checksum.class, c, response.getOutputStream());
456
                            System.out.println("done serializing response.");
457
                        }
458
                        catch(NotAuthorized na)
459
                        {
460
                            na.setDetail_code("1400");
461
                            serializeException(na, response.getOutputStream());
462
                        }
463
                        catch(NotFound nf)
464
                        {
465
                            nf.setDetail_code("1420");
466
                            serializeException(nf, response.getOutputStream());
467
                        }
468
                        catch(InvalidRequest ir)
469
                        {
470
                            ir.setDetail_code("1402");
471
                            serializeException(ir, response.getOutputStream());
472
                        }
473
                        catch(ServiceFailure sf)
474
                        {
475
                            sf.setDetail_code("1410");
476
                            serializeException(sf, response.getOutputStream());
477
                        }
478
                        catch(InvalidToken it)
479
                        {
480
                            it.setDetail_code("1430");
481
                            serializeException(it, response.getOutputStream());
482
                        }
483
                        status = true;
484
                    }
485 5763 berkley
                } else if(resource.equals(RESOURCE_MONITOR)) {
486
                    //health monitoring calls
487
                    System.out.println("processing monitor request");
488
                    String pathInfo = request.getPathInfo();
489 5770 berkley
                    if(httpVerb == GET)
490
                    {
491
                        System.out.println("verb is GET");
492
                        System.out.println("pathInfo is " + pathInfo);
493
                        pathInfo = pathInfo.substring(1);
494 5763 berkley
                        HealthService hs = new HealthService(request, response);
495 5770 berkley
                        if (pathInfo.toLowerCase().equals("ping")) {
496
                            System.out.println("processing ping request");
497
                            hs.ping();
498
                        } else if (pathInfo.toLowerCase().equals("status")) {
499
                            System.out.println("processing status request");
500
                            hs.getStatus();
501
                        } else if (pathInfo.toLowerCase().equals("object")) {
502
                            System.out.println("processing object request");
503
                            boolean day = false;
504
                            Identifier pid = null;
505
                            String url = null;
506
                            ObjectFormat of = null;
507
                            Date time = null;
508
509
                            if(params.containsKey("day"))
510
                            {
511
                               day = true;
512
                            }
513
                            if(params.containsKey("pid"))
514
                            {
515
                                String id = params.get("pid")[0];
516
                                pid = new Identifier();
517
                                pid.setValue(id);
518
                            }
519
                            if(params.containsKey("url"))
520
                            {
521
                                url = params.get("url")[0];
522
                            }
523
                            if(params.containsKey("format"))
524
                            {
525
                                String format = params.get("format")[0];
526
                                of = ObjectFormat.convert(format);
527
                            }
528
                            if(params.containsKey("time"))
529
                            {
530
                                String t = params.get("time")[0];
531
                                time = dateFormat.parse(t);
532
                            }
533
534
                            hs.getObjectStatistics(day, pid, url, of, time);
535
                        } else if (pathInfo.toLowerCase().equals("event")) {
536
                            System.out.println("processing event request");
537
                            boolean day = false;
538
                            Identifier pid = null;
539
                            Date created = null;
540
                            ObjectFormat of = null;
541
                            Date time = null;
542
                            String ipAddress = null;
543
                            String event = null;
544
545
                            if(params.containsKey("day"))
546
                            {
547
                               day = true;
548
                            }
549
                            if(params.containsKey("pid"))
550
                            {
551
                                String id = params.get("pid")[0];
552
                                pid = new Identifier();
553
                                pid.setValue(id);
554
                            }
555
                            if(params.containsKey("created"))
556
                            {
557
                                String t = params.get("created")[0];
558
                                created = dateFormat.parse(t);
559
                            }
560
                            if(params.containsKey("format"))
561
                            {
562
                                String format = params.get("format")[0];
563
                                of = ObjectFormat.convert(format);
564
                            }
565
                            if(params.containsKey("eventtime"))
566
                            {
567
                                String t = params.get("eventtime")[0];
568
                                time = dateFormat.parse(t);
569
                            }
570
                            if(params.containsKey("ip_address"))
571
                            {
572
                                ipAddress = params.get("ip_address")[0];
573
                            }
574
                            if(params.containsKey("event"))
575
                            {
576
                                event = params.get("event")[0];
577
                            }
578
579
                            hs.getOperationStatistics(day, pid, of, created, time, ipAddress, event);
580
                        }
581 5763 berkley
                    }
582
                    status = true;
583 5657 berkley
                }
584
585
                if (!status)
586
                {
587
                    response.setStatus(400);
588
                    printError("Incorrect parameters!", response);
589
                }
590 5211 jones
            } else {
591 5512 berkley
                response.setStatus(400);
592 5657 berkley
                printError("Incorrect resource!", response);
593 5211 jones
            }
594
        } catch (Exception e) {
595 5657 berkley
            logMetacat.error(e.getMessage());
596
            e.printStackTrace();
597 5211 jones
        }
598
    }
599 5374 berkley
600
    /**
601 5692 berkley
     * create the root node registry response.
602
     * @throws JiBXException
603
     * @throws IOException
604
     */
605
    private void createNodeResponse()
606
        throws JiBXException, IOException
607
    {
608
        NodeList nl = new NodeList();
609
        Node n = new Node();
610
        NodeReference nr = new NodeReference();
611
        nr.setValue(request.getRequestURL().toString());
612
        n.setIdentifier(nr);
613
        n.setBaseURL(request.getRequestURL().toString());
614
        n.setDescription("Metacat DataONE Node");
615 5778 berkley
        n.setName("Metacat WAR version 2011.01.06.11.20");
616 5692 berkley
        n.setType(NodeType.convert("mn"));
617
618
        //create the services
619
        Service mnCrud03 = new Service();
620
        mnCrud03.setName("Metacat MN_Crud Services Version 0.3");
621
        mnCrud03.setVersion("0.3");
622
623
        Service mnCrud04 = new Service();
624
        mnCrud04.setName("Metacat MN_Crud Services Version 0.4");
625
        mnCrud04.setVersion("0.4");
626
627
        Service mnCrud09 = new Service();
628
        mnCrud09.setName("Metacat MN_Crud Services Version 0.9");
629
        mnCrud09.setVersion("0.9");
630
631
        Service mnReplication03 = new Service();
632
        mnReplication03.setName("Metcat MN_Replication Version 0.3");
633
        mnReplication03.setVersion("0.3");
634
635
        Service mnHealth04 = new Service();
636
        mnHealth04.setName("Metacat MN_Health Version 0.4");
637
        mnHealth04.setVersion("0.4");
638
639
        Service mnHealth06 = new Service();
640
        mnHealth06.setName("Metacat MN_Health Version 0.6");
641
        mnHealth06.setVersion("0.6");
642
643
        Service mnAuthentication07 = new Service();
644
        mnAuthentication07.setName("Metacat MN_Authentication Version 0.7");
645
        mnAuthentication07.setVersion("0.7");
646
647
        Service mnAuthorization07 = new Service();
648
        mnAuthorization07.setName("Metacat MN_Authorization Version 0.7");
649
        mnAuthorization07.setVersion("0.7");
650
651
                                    //name, rest, implemented
652
        mnCrud03.addMethod(getServiceMethod("MN_crud.get()", "/object/<guid>", true));
653
        mnCrud03.addMethod(getServiceMethod("MN_crud.getSystemMetadata()", "/meta/<guid>", true));
654
        mnCrud04.addMethod(getServiceMethod("MN_crud.create()", "/object/<guid>", true));
655
        mnCrud04.addMethod(getServiceMethod("MN_crud.update()", "/object/<guid>", true));
656
        mnCrud09.addMethod(getServiceMethod("MN_crud.delete()", "/object/<guid>", true));
657
        mnCrud03.addMethod(getServiceMethod("MN_crud.describe()", "/object/<guid>", true));
658
        mnCrud03.addMethod(getServiceMethod("MN_crud.getChecksum()", "/checksum/<guid>", true));
659
        mnCrud03.addMethod(getServiceMethod("MN_crud.getLogRecords()", "/log", true));
660
        mnReplication03.addMethod(getServiceMethod("MN_replication.listObjects()", "/object", true));
661
        mnHealth04.addMethod(getServiceMethod("MN_health.ping()", "/health/ping", false));
662
        mnHealth04.addMethod(getServiceMethod("MN_health.getObjectStatistics()", "/monitor/object/<guid>", false));
663
        mnHealth06.addMethod(getServiceMethod("MN_health.getStatus()", "/health/status", false));
664
        mnAuthentication07.addMethod(getServiceMethod("MN_authentication.login()", "/account/login", false));
665
        mnAuthentication07.addMethod(getServiceMethod("MN_authentication.logout()", "/account/logout", false));
666
        mnAuthorization07.addMethod(getServiceMethod("MN_authorization.isAuthorized()", "/isAuthorized/<guid>", false));
667
668
        Services ss = new Services();
669
        ss.addService(mnCrud03);
670
        ss.addService(mnCrud04);
671
        ss.addService(mnCrud09);
672
        ss.addService(mnReplication03);
673
        ss.addService(mnHealth04);
674
        ss.addService(mnHealth06);
675
        ss.addService(mnAuthentication07);
676
        ss.addService(mnAuthorization07);
677
        nl.addNode(n);
678 5695 berkley
        response.setContentType("text/xml");
679
        response.setStatus(200);
680 5692 berkley
        serializeServiceType(NodeList.class, nl, response.getOutputStream());
681
    }
682
683
    /**
684 5651 berkley
     * MN_crud.describe()
685
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.describe
686
     * @param guid
687
     */
688
    private void describeObject(String guid)
689
    {
690
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
691
        OutputStream out = null;
692
        try
693
        {
694
            out = response.getOutputStream();
695
        }
696
        catch(Exception e)
697
        {
698
            logMetacat.error("Error getting output stream in ResourceHandler.describeObject: " + e.getMessage());
699
            return;
700
        }
701
        response.setStatus(200);
702
        response.setContentType("text/xml");
703
        AuthToken token = new AuthToken(sessionId);
704
        CrudService cs = CrudService.getInstance();
705
        Identifier id = new Identifier();
706
        id.setValue(guid);
707
        try
708
        {
709
            DescribeResponse dr = cs.describe(token, id);
710
            DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SZ");
711
            response.addHeader("guid", guid);
712
            response.addHeader("checksum", dr.getDataONE_Checksum().getValue());
713 5652 berkley
            response.addHeader("checksum_algorithm", dr.getDataONE_Checksum().getAlgorithm().name());
714 5651 berkley
            response.addHeader("content_length", dr.getContent_Length() + "");
715
            response.addHeader("last_modified", dateFormat.format(dr.getLast_Modified()));
716
            response.addHeader("format", dr.getDataONE_ObjectFormat().toString());
717
        }
718
        catch(InvalidRequest ir)
719
        {
720
            serializeException(ir, out);
721
        }
722
        catch(NotImplemented ni)
723
        {
724
            serializeException(ni, out);
725
        }
726
        catch(NotAuthorized na)
727
        {
728
            serializeException(na, out);
729
        }
730
        catch(ServiceFailure sf)
731
        {
732
            serializeException(sf, out);
733
        }
734
        catch(NotFound nf)
735
        {
736
            serializeException(nf, out);
737
        }
738
        catch(InvalidToken it)
739
        {
740
            serializeException(it, out);
741
        }
742
    }
743
744
    /**
745 5390 berkley
     * get the logs from the CrudService based on passed params.  Available
746
     * params are token, fromDate, toDate, event.  See
747
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
748
     * for more info
749
     */
750
    private void getLog()
751
    {
752
        OutputStream out = null;
753
        try
754
        {
755
            out = response.getOutputStream();
756 5515 berkley
            response.setStatus(200);
757 5450 berkley
            response.setContentType("text/xml");
758 5390 berkley
            AuthToken token = new AuthToken(sessionId);
759
            String fromDateS = params.get("fromDate")[0];
760 5418 berkley
            System.out.println("param fromDateS: " + fromDateS);
761 5390 berkley
            Date fromDate = null;
762
            String toDateS = params.get("toDate")[0];
763 5418 berkley
            System.out.println("param toDateS: " + toDateS);
764 5390 berkley
            Date toDate = null;
765
            String eventS = params.get("event")[0];
766
            Event event = null;
767
            if(fromDateS != null)
768
            {
769 5429 berkley
                //fromDate = dateFormat.parse(fromDateS);
770
                fromDate = parseDateAndConvertToGMT(fromDateS);
771 5390 berkley
            }
772
            if(toDateS != null)
773
            {
774 5429 berkley
                //toDate = dateFormat.parse(toDateS);
775
                toDate = parseDateAndConvertToGMT(toDateS);
776 5390 berkley
            }
777
            if(eventS != null)
778
            {
779
                event = Event.convert(eventS);
780
            }
781 5418 berkley
            System.out.println("fromDate: " + fromDate + " toDate: " + toDate);
782 5395 berkley
783 5418 berkley
            System.out.println("calling crudservice.getLogRecords");
784 5390 berkley
            Log log = CrudService.getInstance().getLogRecords(token, fromDate, toDate, event);
785
            serializeServiceType(Log.class, log, out);
786
        }
787
        catch(Exception e)
788
        {
789
            String msg = "Could not get logs from CrudService: " + e.getMessage();
790 5617 berkley
            response.setStatus(500);
791 5390 berkley
            ServiceFailure sf = new ServiceFailure("1490", msg);
792
            logMetacat.error(msg);
793
            e.printStackTrace();
794
            serializeException(sf, out);
795
        }
796
    }
797
798
    /**
799 5374 berkley
     *  copies request parameters to a hashtable which is given as argument to native metacathandler functions
800
     */
801
    private void initParams() {
802 5211 jones
803 5374 berkley
        String name = null;
804
        String[] value = null;
805
        Enumeration paramlist = request.getParameterNames();
806
        while (paramlist.hasMoreElements()) {
807
            name = (String) paramlist.nextElement();
808
            value = request.getParameterValues(name);
809
            params.put(name, value);
810
        }
811
    }
812
813 5211 jones
    /**
814 5374 berkley
     *
815
     * Load user details of metacat session from the request
816
     *
817
     */
818
    private void loadSessionData()
819
      throws Exception
820
    {
821
        SessionData sessionData = RequestUtil.getSessionData(request);
822
        try
823
        {
824
            username = null;
825
            password = null;
826
            groupNames = null;
827
            sessionId = null;
828
829
            boolean validSession = false;
830
            SessionService ss = SessionService.getInstance();
831 5410 berkley
            System.out.println("sessionData: " + sessionData);
832 5423 berkley
            if(sessionData == null)
833
            {
834
                username = "public";
835
                sessionId = "0";
836
                System.out.println("sessiondata is null.  Creating a public session.");
837
                return;
838
            }
839
840 5410 berkley
            System.out.println("username: " + sessionData.getUserName());
841
            System.out.println("sessionid: " + sessionData.getId());
842 5374 berkley
            //validate the session
843 5410 berkley
            if(ss.isSessionRegistered(sessionData.getId()) &&
844
               !(sessionData.getUserName().equals("public") || sessionData.getId().equals("0")))
845 5374 berkley
            {
846
                validSession = true;
847
            }
848
849
            if(validSession)
850
            {
851
                //if the session is valid, set these variables
852
                username = sessionData.getUserName();
853
                password = sessionData.getPassword();
854
                groupNames = sessionData.getGroupNames();
855
                sessionId = sessionData.getId();
856 5386 berkley
                System.out.println("setting sessionid to " + sessionId);
857
                System.out.println("username: " + username);
858 5374 berkley
            }
859
860
            //if the session is not valid or the username is null, set
861
            //username to public
862
            if (username == null)
863
            {
864 5386 berkley
                System.out.println("setting username to public.");
865 5374 berkley
                username = "public";
866
            }
867
        }
868
        catch(Exception e)
869
        {
870 5423 berkley
            e.printStackTrace();
871 5374 berkley
            throw new Exception("Could not load the session data: " + e.getMessage());
872
        }
873
    }
874
875
    /**
876
     * generate missing system metadata for any science metadata objects
877
     * that don't already have it. https://trac.dataone.org/ticket/591
878 5381 berkley
     *
879
     * called with POST meta/?op=generatemissingsystemmetadata
880 5374 berkley
     */
881
    private void generateMissingSystemMetadata()
882
    {
883 5381 berkley
        AuthToken token = new AuthToken(sessionId);
884
        CrudService.getInstance().generateMissingSystemMetadata(token);
885 5374 berkley
    }
886
887
    /**
888
     *  Earthgrid API > Identifier Service > isRegistered Function :
889
     *  calls MetacatHandler > handleIdIsRegisteredAction
890 5286 jones
     * @param guid
891 5211 jones
     * @throws IOException
892
     */
893 5286 jones
    private void isRegistered(String guid) throws IOException
894
    {
895
896
        // Look up the localId for this guid
897
        IdentifierManager im = IdentifierManager.getInstance();
898
        String localId = "";
899
        try {
900
            localId = im.getLocalId(guid);
901
        } catch (McdbDocNotFoundException e) {
902
            // TODO: Need to return the proper DataONE exception
903
        }
904
905
        params.put("docid", new String[] { localId });
906 5211 jones
        PrintWriter out = response.getWriter();
907 5515 berkley
        response.setStatus(200);
908 5450 berkley
        response.setContentType("text/xml");
909 5211 jones
        handler.handleIdIsRegisteredAction(out, params, response);
910
        out.close();
911
    }
912
913
    /**
914 5374 berkley
     * Earthgrid API > Identifier Service > getAllDocIds Function :
915
     * calls MetacatHandler > handleGetAllDocidsAction
916 5211 jones
     * @throws IOException
917
     */
918
    private void getAllDocIds() throws IOException {
919
        PrintWriter out = response.getWriter();
920 5515 berkley
        response.setStatus(200);
921 5450 berkley
        response.setContentType("text/xml");
922 5211 jones
        handler.handleGetAllDocidsAction(out, params, response);
923
        out.close();
924
    }
925
926
    /**
927 5374 berkley
     * Earthgrid API > Identifier Service > getNextRevision Function :
928
     * calls MetacatHandler > handleGetRevisionAndDocTypeAction
929 5286 jones
     * @param guid
930 5211 jones
     * @throws IOException
931
     */
932 5286 jones
    private void getNextRevision(String guid) throws IOException
933
    {
934
        params.put("docid", new String[] { guid });
935 5211 jones
        PrintWriter out = response.getWriter();
936 5515 berkley
        response.setStatus(200);
937 5450 berkley
        response.setContentType("text/xml");
938 5211 jones
        //handler.handleGetRevisionAndDocTypeAction(out, params);
939
940
        try {
941
            // Make sure there is a docid
942 5286 jones
            if (guid == null || guid.equals("")) {
943 5211 jones
                throw new Exception("User didn't specify docid!");
944 5286 jones
            }
945 5211 jones
946 5286 jones
            // Look up the localId for this guid
947
            IdentifierManager im = IdentifierManager.getInstance();
948
            String localId = "";
949
            try {
950
                localId = im.getLocalId(guid);
951
            } catch (McdbDocNotFoundException e) {
952
                // TODO: Need to return the proper DataONE exception
953
            }
954
955 5211 jones
            // Create a DBUtil object
956
            DBUtil dbutil = new DBUtil();
957
            // Get a rev and doctype
958
            String revAndDocType = dbutil
959 5286 jones
                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
960 5211 jones
            int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
961
962
            out.println("<?xml version=\"1.0\"?>");
963
            out.print("<next-revision>");
964
            out.print(revision);
965
            out.print("</next-revision>");
966
967
        } catch (Exception e) {
968
            // Handle exception
969 5512 berkley
            response.setStatus(500);
970 5211 jones
            out.println("<?xml version=\"1.0\"?>");
971
            out.println("<error>");
972
            out.println(e.getMessage());
973
            out.println("</error>");
974
        }
975
976
        out.close();
977
    }
978
979
    /**
980 5374 berkley
     * Earthgrid API > Identifier Service > getNextObject Function :
981
     * calls MetacatHandler > handleGetMaxDocidAction
982 5211 jones
     * @throws IOException
983
     */
984
    private void getNextObject() throws IOException {
985
        PrintWriter out = response.getWriter();
986 5515 berkley
        response.setStatus(200);
987 5450 berkley
        response.setContentType("text/xml");
988 5211 jones
        handler.handleGetMaxDocidAction(out, params, response);
989
        out.close();
990
    }
991
992
    /**
993 5299 jones
     * Implements REST version of DataONE CRUD API --> get
994 5282 jones
     * @param guid ID of data object to be read
995 5211 jones
     */
996 5450 berkley
    private void getObject(String guid) {
997
        CrudService cs = CrudService.getInstance();
998
        cs.setParamsFromRequest(request);
999
        AuthToken token = new AuthToken(sessionId);
1000
        OutputStream out = null;
1001
        try {
1002
            out = response.getOutputStream();
1003 5515 berkley
            response.setStatus(200);
1004 5450 berkley
            response.setContentType("text/xml");
1005
            if(guid != null)
1006
            { //get a specific document
1007
                Identifier id = new Identifier();
1008
                id.setValue(guid);
1009
                try
1010
                {
1011
                    if(token == null)
1012
                    {
1013
                        token = new AuthToken("Public");
1014
                    }
1015
                    InputStream data = cs.get(token, id);
1016
                    IOUtils.copyLarge(data, response.getOutputStream());
1017
                }
1018
                catch(InvalidToken it)
1019
                {
1020 5617 berkley
                    response.setStatus(500);
1021 5450 berkley
                    serializeException(it, out);
1022
                }
1023
                catch(ServiceFailure sf)
1024
                {
1025 5617 berkley
                    response.setStatus(500);
1026 5450 berkley
                    serializeException(sf, out);
1027
                }
1028
                catch(NotAuthorized na)
1029
                {
1030 5617 berkley
                    response.setStatus(500);
1031 5450 berkley
                    serializeException(na, out);
1032
                }
1033
                catch(NotFound nf)
1034
                {
1035 5617 berkley
                    response.setStatus(500);
1036 5450 berkley
                    serializeException(nf, out);
1037
                }
1038
                catch(NotImplemented ni)
1039
                {
1040 5617 berkley
                    response.setStatus(500);
1041 5450 berkley
                    serializeException(ni, out);
1042
                }
1043
                catch(Exception e)
1044
                {
1045 5617 berkley
                    response.setStatus(500);
1046 5450 berkley
                    System.out.println("Error with Crud.get().  " +
1047
                            "If this is an 'Exception producing data' error, " +
1048
                            "go to CrudService.get() for better debugging.  " +
1049
                            "Here's the error: " + e.getMessage());
1050
                    e.printStackTrace();
1051
                    ServiceFailure sf = new ServiceFailure("1030",
1052
                            "IO Error in ResourceHandler.getObject: " + e.getMessage());
1053
                    serializeException(sf, out);
1054
                }
1055
            }
1056
            else
1057
            { //call listObjects with specified params
1058
                Date startTime = null;
1059
                Date endTime = null;
1060
                ObjectFormat objectFormat = null;
1061
                boolean replicaStatus = false;
1062
                int start = 0;
1063 5481 berkley
                //TODO: make the max count into a const
1064 5450 berkley
                int count = 1000;
1065
                Enumeration paramlist = request.getParameterNames();
1066
                while (paramlist.hasMoreElements())
1067
                { //parse the params and make the crud call
1068
                    String name = (String) paramlist.nextElement();
1069
                    String[] value = (String[])request.getParameterValues(name);
1070
                    /*for(int i=0; i<value.length; i++)
1071
                    {
1072
                        System.out.println("name: " + name + " value: " + value[i]);
1073
                    }*/
1074
                    if(name.equals("startTime") && value != null)
1075
                    {
1076
                        try
1077
                        {
1078
                          //startTime = dateFormat.parse(value[0]);
1079
                            startTime = parseDateAndConvertToGMT(value[0]);
1080
                        }
1081
                        catch(Exception e)
1082
                        {  //if we can't parse it, just don't use the startTime param
1083
                            System.out.println("Could not parse startTime: " + value[0]);
1084
                            startTime = null;
1085
                        }
1086
                    }
1087
                    else if(name.equals("endTime") && value != null)
1088
                    {
1089
                        try
1090
                        {
1091
                          //endTime = dateFormat.parse(value[0]);
1092
                            endTime = parseDateAndConvertToGMT(value[0]);
1093
                        }
1094
                        catch(Exception e)
1095
                        {  //if we can't parse it, just don't use the endTime param
1096
                            System.out.println("Could not parse endTime: " + value[0]);
1097
                            endTime = null;
1098
                        }
1099
                    }
1100
                    else if(name.equals("objectFormat") && value != null)
1101
                    {
1102
                        objectFormat = ObjectFormat.convert(value[0]);
1103
                    }
1104
                    else if(name.equals("replicaStatus") && value != null)
1105
                    {
1106
                        if(value != null &&
1107
                           value.length > 0 &&
1108
                           (value[0].equals("true") || value[0].equals("TRUE") || value[0].equals("YES")))
1109
                        {
1110
                            replicaStatus = true;
1111
                        }
1112
                    }
1113
                    else if(name.equals("start") && value != null)
1114
                    {
1115
                        start = new Integer(value[0]).intValue();
1116
                    }
1117
                    else if(name.equals("count") && value != null)
1118
                    {
1119
                        count = new Integer(value[0]).intValue();
1120
                    }
1121
                }
1122
                //make the crud call
1123 5510 berkley
                System.out.println("token: " + token + " startTime: " + startTime +
1124 5450 berkley
                        " endtime: " + endTime + " objectFormat: " +
1125
                        objectFormat + " replicaStatus: " + replicaStatus +
1126
                        " start: " + start + " count: " + count);
1127 5510 berkley
1128 5450 berkley
                ObjectList ol = cs.listObjects(token, startTime, endTime,
1129
                        objectFormat, replicaStatus, start, count);
1130
1131
                StringReader sr = new StringReader(ol.toString());
1132 5515 berkley
                out = response.getOutputStream();
1133
                response.setStatus(200);
1134 5450 berkley
                response.setContentType("text/xml");
1135
                // Serialize and write it to the output stream
1136
1137
                try {
1138
                    serializeServiceType(ObjectList.class, ol, out);
1139
                } catch (JiBXException e) {
1140
                    throw new ServiceFailure("1190", "Failed to serialize ObjectList: " + e.getMessage());
1141
                }
1142
            }
1143
        } catch (BaseException e) {
1144 5617 berkley
                response.setStatus(500);
1145 5450 berkley
                serializeException(e, out);
1146
        } catch (IOException e) {
1147
            e.printStackTrace();
1148 5617 berkley
            response.setStatus(500);
1149 5450 berkley
            ServiceFailure sf = new ServiceFailure("1030",
1150
                    "IO Error in ResourceHandler.getObject: " + e.getMessage());
1151
            serializeException(sf, out);
1152
        } catch(NumberFormatException ne) {
1153 5617 berkley
            response.setStatus(500);
1154 5450 berkley
            InvalidRequest ir = new InvalidRequest("1030", "Invalid format for parameter: " + ne.getMessage());
1155
            serializeException(ir, out);
1156
        } catch (Exception e) {
1157
            e.printStackTrace();
1158 5617 berkley
            response.setStatus(500);
1159 5450 berkley
            ServiceFailure sf = new ServiceFailure("1030",
1160
                    "Exception " + e.getClass().getName() + " raised while handling listObjects request: " +
1161
                    e.getMessage());
1162
            serializeException(sf, out);
1163
        }
1164
    }
1165 5428 berkley
1166
    /**
1167
     * parse a date and return it in GMT if it ends with a 'Z'
1168
     * @param date
1169
     * @return
1170
     * @throws ParseException
1171
     */
1172
    private Date parseDateAndConvertToGMT(String date) throws ParseException
1173
    {
1174 5429 berkley
        try
1175
        {   //the format we want
1176
            return dateFormat.parse(date);
1177
        }
1178
        catch(java.text.ParseException pe)
1179
        {   //try another legacy format
1180
            DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
1181
            dateFormat2.setTimeZone(TimeZone.getTimeZone("GMT-0"));
1182
            return dateFormat2.parse(date);
1183
        }
1184 5428 berkley
    }
1185 5211 jones
1186
    /**
1187 5332 jones
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
1188
     * @param guid ID of data object to be read
1189
     */
1190
    private void getSystemMetadataObject(String guid) {
1191 5337 berkley
        CrudService cs = CrudService.getInstance();
1192
        cs.setParamsFromRequest(request);
1193 5386 berkley
        AuthToken token = new AuthToken(sessionId);
1194 5332 jones
        OutputStream out = null;
1195
        try {
1196 5450 berkley
            response.setContentType("text/xml");
1197 5515 berkley
            response.setStatus(200);
1198 5332 jones
            out = response.getOutputStream();
1199
            Identifier id = new Identifier();
1200
            id.setValue(guid);
1201
            SystemMetadata sysmeta = cs.getSystemMetadata(token, id);
1202
1203
            // Serialize and write it to the output stream
1204
            try {
1205 5481 berkley
                //TODO: look at the efficiency of this method.  The system metadata
1206
                //is read from metacat (in CrudService) as xml, then serialized
1207
                //to a SystemMetadat object, then returned here, then serizlized
1208
                //back to XML to be sent to the response.
1209 5390 berkley
                serializeServiceType(SystemMetadata.class, sysmeta, out);
1210 5332 jones
            } catch (JiBXException e) {
1211 5356 berkley
                throw new ServiceFailure("1190", "Failed to serialize SystemMetadata: " + e.getMessage());
1212 5332 jones
            }
1213
        } catch (BaseException e) {
1214 5617 berkley
            response.setStatus(500);
1215 5332 jones
                serializeException(e, out);
1216
        } catch (IOException e) {
1217 5617 berkley
            response.setStatus(500);
1218 5414 berkley
            ServiceFailure sf = new ServiceFailure("1030",
1219
                    "Error in ResourceHandler.getSystemMetadataObject: " + e.getMessage());
1220 5332 jones
            serializeException(sf, out);
1221
        } finally {
1222
            IOUtils.closeQuietly(out);
1223
        }
1224
    }
1225
1226
    /**
1227 5390 berkley
     * serialize an object of type to out
1228
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
1229
     * @param object the object to serialize
1230
     * @param out the stream to serialize it to
1231
     * @throws JiBXException
1232
     */
1233
    private void serializeServiceType(Class type, Object object, OutputStream out)
1234
      throws JiBXException
1235
    {
1236
        IBindingFactory bfact = BindingDirectory.getFactory(type);
1237
        IMarshallingContext mctx = bfact.createMarshallingContext();
1238
        mctx.marshalDocument(object, "UTF-8", null, out);
1239
    }
1240
1241
    /**
1242
     * deserialize an object of type from is
1243
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
1244
     * @param is the stream to deserialize from
1245
     * @throws JiBXException
1246
     */
1247
    private Object deserializeServiceType(Class type, InputStream is)
1248
      throws JiBXException
1249
    {
1250
        IBindingFactory bfact = BindingDirectory.getFactory(type);
1251
        IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1252
        Object o = (Object) uctx.unmarshalDocument(is, null);
1253
        return o;
1254
    }
1255
1256
    /**
1257 5211 jones
     * Earthgrid API > Query Service > Query Function : translates ecogrid query document to metacat query
1258
     * then calls DBQuery > createResultDocument function and then again translate resultset to ecogrid resultset
1259
     *
1260
     * NOTE:
1261
     *      This is the only method that uses EcoGrid classes for its implementation.
1262
     *      It does so because it takes an EcoGrid Query as input, and outputs an
1263
     *      EcoGrid ResultSet document.  These documents are parsed by the auto-generated
1264
     *      EcoGrid classes from axis, and so we link to them here rather than re-inventing them.
1265
     *      This creates a circular dependency, because the Metacat classes are needed
1266
     *      to build the EcoGrid implementation, and the EcoGrid jars are needed to build this query()
1267
     *      method.  This circularity could be resolved by moving the EcoGrid classes
1268
     *      to Metacat directly.  As we transition away from EcoGrid SOAP methods in
1269
     *      favor of these REST interfaces, this circular dependency can be eliminated.
1270
     *
1271
     * @throws Exception
1272
     */
1273
    private void query() throws Exception {
1274
        /*  This block commented out because of the EcoGrid circular dependency.
1275
         *  For now, query will not be supported until the circularity can be
1276 5286 jones
         *  resolved, probably by moving the ecogrid query syntax transformers
1277 5211 jones
         *  directly into the Metacat codebase.  MBJ 2010-02-03
1278
1279
        try {
1280
            EcogridQueryParser parser = new EcogridQueryParser(request
1281
                    .getReader());
1282
            parser.parseXML();
1283
            QueryType queryType = parser.getEcogridQuery();
1284
            EcogridJavaToMetacatJavaQueryTransformer queryTransformer =
1285
                new EcogridJavaToMetacatJavaQueryTransformer();
1286
            QuerySpecification metacatQuery = queryTransformer
1287
                    .transform(queryType);
1288
1289
            DBQuery metacat = new DBQuery();
1290
1291
            boolean useXMLIndex = (new Boolean(PropertyService
1292
                    .getProperty("database.usexmlindex"))).booleanValue();
1293
            String xmlquery = "query"; // we don't care the query in resultset,
1294
            // the query can be anything
1295
            PrintWriter out = null; // we don't want metacat result, so set out null
1296
1297
            // parameter: queryspecification, user, group, usingIndexOrNot
1298
            StringBuffer result = metacat.createResultDocument(xmlquery,
1299
                    metacatQuery, out, username, groupNames, useXMLIndex);
1300
1301 5657 berkley
            // create result set transfer
1302 5211 jones
            String saxparser = PropertyService.getProperty("xml.saxparser");
1303
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
1304
                    new StringReader(result.toString()), saxparser, queryType
1305
                            .getNamespace().get_value());
1306
            ResultsetType records = metacatResultsetParser.getEcogridResult();
1307
1308
            System.out
1309
                    .println(EcogridResultsetTransformer.toXMLString(records));
1310
            response.setContentType("text/xml");
1311
            out = response.getWriter();
1312
            out.print(EcogridResultsetTransformer.toXMLString(records));
1313
1314
        } catch (Exception e) {
1315
            e.printStackTrace();
1316
        }*/
1317
        response.setContentType("text/xml");
1318 5512 berkley
        response.setStatus(501);
1319 5211 jones
        PrintWriter out = response.getWriter();
1320
        out.print("<error>Query operation not yet supported by Metacat.</error>");
1321
        out.close();
1322
    }
1323 5319 jones
1324 5394 berkley
    private String streamToString(InputStream is)
1325
    throws IOException
1326
    {
1327 5629 berkley
        return IOUtil.toString(is);
1328 5394 berkley
    }
1329
1330
    private InputStream stringToStream(String s)
1331
    throws IOException
1332
    {
1333 5760 leinfelder
        ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes(MetaCatServlet.DEFAULT_ENCODING));
1334 5394 berkley
        return bais;
1335
    }
1336
1337 5462 berkley
    /**
1338
     * process a mime multipart message
1339
     * @param is
1340
     * @return
1341
     */
1342 5636 berkley
    /*private Hashtable processMMP(InputStream is)
1343 5462 berkley
      throws IOException
1344
    {
1345 5481 berkley
        //TODO: verify that this is how the RFC for MMP should work
1346
        //SORTAHACK: Since mmp seems to have a bug where large object parts get truncated,
1347 5462 berkley
        //parse the stream here.  This has the disavantage of putting the
1348
        //stream into memory.
1349
        InputStream object = null;
1350
        InputStream sysmeta = null;
1351 5616 berkley
        String s = IOUtils.toString(is);
1352 5636 berkley
        System.out.println("mime: " + s);
1353 5462 berkley
        //figure out what the boundary marker is
1354
        String searchString = "boundary=";
1355
        int searchStringIndex = s.indexOf(searchString);
1356
        String boundary = s.substring(searchStringIndex + searchString.length() + 1,
1357
                s.indexOf("\"", searchStringIndex + searchString.length() + 1));
1358
        boundary = "--" + boundary;
1359
        //System.out.println("boundary is " + boundary);
1360
1361
        //find the system metadata
1362
        searchString = "Content-Disposition: attachment; filename=systemmetadata";
1363
        searchStringIndex = s.indexOf(searchString);
1364 5616 berkley
        String sm = s.substring(searchStringIndex +
1365
                searchString.length() + 2,
1366
                s.indexOf(boundary, searchStringIndex));
1367
        sysmeta = new ByteArrayInputStream(sm.getBytes());
1368 5462 berkley
1369
        //find the object
1370
        searchString = "Content-Disposition: attachment; filename=object";
1371
        searchStringIndex = s.indexOf(searchString);
1372 5616 berkley
        String o = s.substring(searchStringIndex +
1373
                searchString.length() + 2,
1374
                s.indexOf(boundary, searchStringIndex));
1375
        object = new ByteArrayInputStream(o.getBytes());
1376 5462 berkley
1377
        Hashtable h = new Hashtable();
1378
        h.put("object", object);
1379
        h.put("systemmetadata", sysmeta);
1380 5616 berkley
1381 5617 berkley
        //System.out.println("o: \"" + o + "\"");
1382
        //System.out.println("sm: \"" + sm + "\"");
1383 5462 berkley
        return h;
1384
    }
1385 5636 berkley
    */
1386 5637 berkley
1387 5639 berkley
    protected static String[] findBoundaryString(InputStream is)
1388 5637 berkley
        throws IOException
1389 5629 berkley
    {
1390 5639 berkley
        String[] endResult = new String[2];
1391 5637 berkley
        String boundary = "";
1392 5639 berkley
        String searchString = "boundary=";
1393
        boolean doneWithCurrentArray = false;
1394 5637 berkley
        byte[] b = new byte[1024];
1395 5639 berkley
        int numbytes = is.read(b, 0, 1024);
1396
        while(numbytes != -1)
1397 5636 berkley
        {
1398 5639 berkley
            String s = new String(b, 0, numbytes);
1399
1400
            int[] result = StreamUtil.lookForMatch(searchString, s);
1401
            int searchStringIndex = s.indexOf(searchString);
1402
            if(s.indexOf("\"", searchStringIndex + searchString.length() + 1) == -1)
1403
            { //the end of the boundary is in the next byte array
1404
                boundary = s.substring(searchStringIndex + searchString.length() + 1, s.length());
1405
            }
1406
            else if(!boundary.startsWith("--"))
1407
            { //we can read the whole boundary from this byte array
1408
                boundary = s.substring(searchStringIndex + searchString.length() + 1,
1409
                    s.indexOf("\"", searchStringIndex + searchString.length() + 1));
1410
                boundary = "--" + boundary;
1411
                endResult[0] = boundary;
1412
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1413
                        s.length());
1414
                break;
1415
            }
1416
            else
1417
            { //we're now reading the 2nd byte array to get the rest of the boundary
1418
                searchString = "\"";
1419
                searchStringIndex = s.indexOf(searchString);
1420
                boundary += s.substring(0, searchStringIndex);
1421
                boundary = "--" + boundary;
1422
                endResult[0] = boundary;
1423
                endResult[1] = s.substring(s.indexOf("\"", searchStringIndex + searchString.length() + 1) + 1,
1424
                        s.length());
1425
                break;
1426
            }
1427 5637 berkley
        }
1428 5639 berkley
        System.out.println("boundary is: " + boundary);
1429
        return endResult;
1430
    }
1431
1432
    protected String writeMMPPartToFile(String beginSearch,
1433
            InputStream is, String boundary, String searchString, File f)
1434
        throws IOException
1435
    {
1436 5640 berkley
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
1437
        logMetacat.info("writing MMP parts");
1438 5670 berkley
        //String s = beginSearch;
1439
        String s = null;
1440 5639 berkley
        FileOutputStream fos = new FileOutputStream(f);
1441
        int numread = 0;
1442
        byte[] b = new byte[1024];
1443
        String writeString = "";
1444
1445
        if(s == null)
1446
        {   //starting with the first part of the stream
1447
            numread = is.read(b, 0, 1024);
1448
            s = new String(b, 0, numread);
1449 5637 berkley
        }
1450
1451 5670 berkley
        if(beginSearch != null)
1452
        {
1453
            s = beginSearch + s;
1454
        }
1455
1456 5639 berkley
        boolean useCurrentS = true;
1457
        boolean searchForBoundary = false;
1458
        String seekString = searchString;
1459 5637 berkley
1460
        while(numread != -1)
1461
        {
1462 5640 berkley
            logMetacat.info("////////////////////////iterating");
1463
            logMetacat.info("searchForBoundary: " + searchForBoundary);
1464
            logMetacat.info("useCurrentS: " + useCurrentS);
1465 5670 berkley
            logMetacat.info("seekString: " + seekString);
1466
            logMetacat.info("in string: " + s);
1467 5639 berkley
            if(searchForBoundary)
1468 5636 berkley
            {
1469 5639 berkley
                seekString = boundary;
1470 5637 berkley
            }
1471
            else
1472
            {
1473 5639 berkley
                seekString = searchString;
1474 5637 berkley
            }
1475
1476 5639 berkley
            int[] result = StreamUtil.lookForMatch(seekString, s);
1477
            if(!useCurrentS)
1478 5637 berkley
            {
1479
                numread = is.read(b, 0, 1024);
1480 5639 berkley
                if(numread != -1)
1481
                {
1482
                    s = new String(b, 0, numread);
1483
                }
1484
                else
1485
                {
1486
                    break;
1487
                }
1488 5637 berkley
            }
1489
1490 5670 berkley
            logMetacat.info("2seekString: " + seekString);
1491
            logMetacat.info("2in string: " + s);
1492 5637 berkley
1493 5639 berkley
            if(result[0] >= 0 && result[1] == seekString.length())
1494
            {
1495 5640 berkley
                //searchString is full in s
1496
                logMetacat.info("seekstring is fully in s");
1497 5639 berkley
                if(!searchForBoundary)
1498
                {   //we're looking for searchString and we found it
1499
                    //chop off the searchString itself and start writing
1500
                    //until we find boundary
1501
                    s = s.substring(result[0] + result[1], s.length());
1502
                    if(s.length() > 0)
1503 5638 berkley
                    {
1504 5639 berkley
                        useCurrentS = true;
1505 5638 berkley
                    }
1506
                    else
1507
                    {
1508 5639 berkley
                        useCurrentS = false;
1509 5638 berkley
                    }
1510 5639 berkley
                    searchForBoundary = true;
1511 5638 berkley
                }
1512 5639 berkley
                else
1513
                {   //we're writing, but we found the boundary in this chunk
1514 5637 berkley
1515 5639 berkley
                    writeString = s.substring(0, result[0]);
1516 5657 berkley
                    //System.out.println("writing1: " + writeString);
1517 5760 leinfelder
                    fos.write(writeString.getBytes(MetaCatServlet.DEFAULT_ENCODING));
1518 5639 berkley
                    //we're done.  break and return;
1519
                    return s.substring(result[0] + result[1], s.length());
1520 5637 berkley
                }
1521
            }
1522 5639 berkley
            else if(result[0] > 0 && result[1] != seekString.length())
1523
            {
1524 5640 berkley
                logMetacat.info("seekstring is partially in s");
1525 5639 berkley
                //seekString is partially in s
1526
                //more specifically, the beginning of seekString is at the end
1527
                //of s
1528
1529
                //get the next chunk right now, see if the beginning matches
1530
                numread = is.read(b, 0, 1024);
1531
                String s2 = new String(b, 0, numread);
1532
                s += s2;
1533 5640 berkley
                useCurrentS = true;
1534 5637 berkley
            }
1535
            else
1536
            {
1537 5640 berkley
                logMetacat.info("seekstring is not in s");
1538 5639 berkley
                //searchString is not in s
1539 5637 berkley
                if(searchForBoundary)
1540
                {
1541 5657 berkley
                    //System.out.println("writing2: " + s);
1542 5760 leinfelder
                    fos.write(s.getBytes(MetaCatServlet.DEFAULT_ENCODING));
1543 5636 berkley
                }
1544 5639 berkley
                numread = is.read(b, 0, 1024);
1545
                if(numread != -1)
1546
                {
1547
                    s = new String(b, 0, numread);
1548
                }
1549
                else
1550
                {
1551
                    break;
1552
                }
1553 5640 berkley
                useCurrentS = true;
1554 5636 berkley
            }
1555 5637 berkley
        }
1556 5639 berkley
        return "";
1557
    }
1558
1559
    protected Hashtable<String, File> writeMMPPartsToFiles(InputStream is)
1560
        throws IOException
1561
    {
1562 5640 berkley
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
1563
        logMetacat.info("Processing Mime Multipart");
1564 5639 berkley
        String[] boundaryResults = findBoundaryString(is);
1565
        String boundary = boundaryResults[0];
1566
        String s = boundaryResults[1];
1567
        String[] searchStrings = {
1568
                "Content-Disposition: attachment; filename=systemmetadata\n\n",
1569
                "Content-Disposition: attachment; filename=object\n\n"};
1570 5637 berkley
1571 5639 berkley
        File[] fileArr = getMMPTempFiles();
1572 5638 berkley
        Hashtable<String, File> h = new Hashtable<String, File>();
1573 5640 berkley
        //System.out.println("==========================Looking for SM");
1574
        //System.out.println("writing sm to " + fileArr[0].getAbsolutePath());
1575
        logMetacat.info("writing mime system metadata to " + fileArr[0].getAbsolutePath());
1576 5670 berkley
        s = writeMMPPartToFile(s.trim(), is, boundary, searchStrings[0], fileArr[0]);
1577
        logMetacat.info("writeMMPPartToFile returned '" + s.trim() + "' after processing the system metadata");
1578 5640 berkley
        //System.out.println("==========================Looking for Object");
1579
        //System.out.println("writing obj to " + fileArr[1].getAbsolutePath());
1580
        logMetacat.info("writing mime object to " + fileArr[1].getAbsolutePath());
1581 5670 berkley
        writeMMPPartToFile(s.trim(), is, boundary, searchStrings[1], fileArr[1]);
1582 5639 berkley
        h.put("sysmeta", fileArr[0]);
1583
        h.put("object", fileArr[1]);
1584 5638 berkley
        return h;
1585 5637 berkley
    }
1586
1587 5639 berkley
    private static File[] getMMPTempFiles()
1588
        throws IOException
1589
    {
1590
        Logger logMetacat = Logger.getLogger(ResourceHandler.class);
1591
        File tmpDir;
1592
        try
1593
        {
1594
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
1595
        }
1596
        catch(PropertyNotFoundException pnfe)
1597
        {
1598
            logMetacat.error("ResourceHandler.writeMMPPartstoFiles: " +
1599
                    "application.tmpDir not found.  Using /tmp instead.");
1600
            tmpDir = new File("/tmp");
1601
        }
1602
        long datetimetag = new Date().getTime();
1603
        File smFile = new File(tmpDir, "sm." + datetimetag + ".tmp");
1604
        File objFile = new File(tmpDir, "obj." + datetimetag + ".tmp");
1605
        File[] fileArr = {smFile, objFile};
1606
        return fileArr;
1607
    }
1608
1609 5637 berkley
    /**
1610
     * return a vector where the first element is a string that represents the system
1611
     * metadata and the 2nd element is an InputStream that is the object
1612
     */
1613 5638 berkley
    protected Hashtable<String, File> processMMP(final InputStream is)
1614 5637 berkley
      throws IOException
1615
    {
1616
        return writeMMPPartsToFiles(is);
1617 5636 berkley
    }
1618 5462 berkley
1619 5211 jones
    /**
1620
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction
1621
     *
1622 5319 jones
     * @param guid ID of data object to be inserted or updated
1623 5211 jones
     * @throws IOException
1624
     */
1625 5319 jones
    private void putObject(String guid, String action) {
1626
        logMetacat.debug("Entering putObject: " + guid + "/" + action);
1627
        OutputStream out = null;
1628 5642 berkley
        Hashtable<String, File> parts = null;
1629 5319 jones
        try {
1630
            out = response.getOutputStream();
1631 5515 berkley
            response.setStatus(200);
1632 5450 berkley
            response.setContentType("text/xml");
1633 5319 jones
        } catch (IOException e1) {
1634
            logMetacat.error("Could not get the output stream for writing in putObject");
1635
        }
1636
        try {
1637 5353 berkley
1638
            // Read the incoming data from its Mime Multipart encoding
1639
            logMetacat.debug("Disassembling MIME multipart form");
1640
            InputStream object = null;
1641
            InputStream sysmeta = null;
1642 5394 berkley
1643 5638 berkley
            try
1644
            {
1645 5670 berkley
                //String req = IOUtils.toString(request.getInputStream());
1646
                //System.out.println("request: " + req);
1647
                //InputStream reqStr = IOUtils.toInputStream(req);
1648
                InputStream reqStr = request.getInputStream();
1649
                parts = processMMP(reqStr);
1650 5638 berkley
                object = new FileInputStream(parts.get("object"));
1651
                sysmeta = new FileInputStream(parts.get("sysmeta"));
1652 5670 berkley
1653 5674 berkley
                /*String obj = IOUtils.toString(object);
1654 5670 berkley
                String sm = IOUtils.toString(sysmeta);
1655
                System.out.println("object: " + obj);
1656
                System.out.println("sm: " + sm);
1657
                object = IOUtils.toInputStream(obj);
1658 5674 berkley
                sysmeta = IOUtils.toInputStream(sm);*/
1659
1660 5638 berkley
            }
1661
            catch(IOException ioe)
1662
            {
1663
                throw new ServiceFailure("1202",
1664
                        "IOException when processing Mime Multipart: " + ioe.getMessage());
1665
            }
1666 5616 berkley
1667 5353 berkley
            if ( action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
1668 5211 jones
1669 5319 jones
                // Check if the objectId exists
1670
                IdentifierManager im = IdentifierManager.getInstance();
1671
                if (im.identifierExists(guid)) {
1672 5356 berkley
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + guid);
1673 5319 jones
                }
1674 5211 jones
1675 5376 berkley
                logMetacat.debug("Commence creation...");
1676
                IBindingFactory bfact =
1677
                    BindingDirectory.getFactory(SystemMetadata.class);
1678
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1679
                SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1680
1681
                CrudService cs = CrudService.getInstance();
1682 5386 berkley
                AuthToken token = new AuthToken(sessionId);
1683 5376 berkley
                cs.setParamsFromRequest(request);
1684
                Identifier id = new Identifier();
1685
                id.setValue(guid);
1686 5750 berkley
                System.out.println("creating object with guid " + id.getValue());
1687 5674 berkley
                Identifier rId = cs.create(token, id, object, m);
1688
                serializeServiceType(Identifier.class, rId, out);
1689 5386 berkley
1690 5353 berkley
            } else if (action.equals(FUNCTION_NAME_UPDATE)) { //handle updates
1691
                IdentifierManager im = IdentifierManager.getInstance();
1692
                CrudService cs = CrudService.getInstance();
1693
                Identifier obsoletedGuid = new Identifier();
1694
                Identifier id = new Identifier();
1695
                id.setValue(guid);
1696 5386 berkley
                AuthToken token = new AuthToken(sessionId);
1697 5353 berkley
1698
                //do some checks
1699
                if(params.get("obsoletedGuid") == null)
1700
                {
1701 5356 berkley
                    throw new InvalidRequest("1202", "obsoletedGuid must be contained in the request parameters.");
1702 5353 berkley
                }
1703
                //get the obsoletedGuid
1704
                String[] obsGuidS = params.get("obsoletedGuid");
1705
                obsoletedGuid.setValue(obsGuidS[0]);
1706
1707
                if (!im.identifierExists(obsoletedGuid.getValue()))
1708
                {
1709 5356 berkley
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1710 5353 berkley
                }
1711
1712
1713
                logMetacat.debug("Commence update...");
1714
1715
                //get the systemmetadata
1716
                IBindingFactory bfact =
1717
                        BindingDirectory.getFactory(SystemMetadata.class);
1718
                    IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1719
                    SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1720
1721
                //do the update
1722
                try
1723
                {
1724
                    cs.setParamsFromRequest(request);
1725
                    Identifier rId = cs.update(token, id, object, obsoletedGuid, m);
1726 5674 berkley
                    serializeServiceType(Identifier.class, rId, out);
1727 5353 berkley
                }
1728
                catch(NotFound e)
1729
                {
1730 5356 berkley
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1731 5353 berkley
                }
1732
1733 5211 jones
            } else {
1734 5356 berkley
                throw new InvalidRequest("1000", "Operation must be create or update.");
1735 5211 jones
            }
1736 5638 berkley
1737
            //clean up the MMP files
1738 5674 berkley
            parts.get("sysmeta").delete();
1739
            parts.get("object").delete();
1740 5319 jones
        } catch (NotAuthorized e) {
1741 5617 berkley
            response.setStatus(500);
1742 5319 jones
            serializeException(e, out);
1743
        } catch (InvalidToken e) {
1744 5617 berkley
            response.setStatus(500);
1745 5319 jones
            serializeException(e, out);
1746
        } catch (ServiceFailure e) {
1747 5617 berkley
            response.setStatus(500);
1748 5319 jones
            serializeException(e, out);
1749
        } catch (IdentifierNotUnique e) {
1750 5617 berkley
            response.setStatus(500);
1751 5319 jones
            serializeException(e, out);
1752
        } catch (UnsupportedType e) {
1753 5617 berkley
            response.setStatus(500);
1754 5319 jones
            serializeException(e, out);
1755
        } catch (InsufficientResources e) {
1756 5617 berkley
            response.setStatus(500);
1757 5319 jones
            serializeException(e, out);
1758
        } catch (InvalidSystemMetadata e) {
1759 5617 berkley
            response.setStatus(500);
1760 5319 jones
            serializeException(e, out);
1761
        } catch (NotImplemented e) {
1762 5617 berkley
            response.setStatus(500);
1763 5319 jones
            serializeException(e, out);
1764
        } catch (InvalidRequest e) {
1765 5617 berkley
            response.setStatus(500);
1766 5319 jones
            serializeException(e, out);
1767 5394 berkley
        } /*catch (MessagingException e) {
1768 5356 berkley
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1769 5319 jones
            serializeException(sf, out);
1770 5636 berkley
        } catch (IOException e) {
1771 5617 berkley
            response.setStatus(500);
1772 5356 berkley
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1773 5319 jones
            serializeException(sf, out);
1774 5636 berkley
        }*/ catch (JiBXException e) {
1775 5617 berkley
            response.setStatus(500);
1776 5320 jones
            e.printStackTrace(System.out);
1777 5356 berkley
            InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e.getMessage());
1778 5320 jones
            serializeException(ism, out);
1779 5211 jones
        }
1780 5642 berkley
        finally
1781
        {
1782
            if(parts != null)
1783
            {
1784 5674 berkley
                parts.get("sysmeta").delete();
1785
                parts.get("object").delete();
1786 5642 berkley
            }
1787
        }
1788 5211 jones
    }
1789
1790
    /**
1791 5657 berkley
     * Handle delete
1792 5287 jones
     * @param guid ID of data object to be deleted
1793 5211 jones
     * @throws IOException
1794
     */
1795 5287 jones
    private void deleteObject(String guid) throws IOException
1796
    {
1797
        // Look up the localId for this global identifier
1798 5657 berkley
        System.out.println("!!!!!!!!!!!!!!!!!deleting object " + guid);
1799 5287 jones
        IdentifierManager im = IdentifierManager.getInstance();
1800
        String localId = "";
1801 5657 berkley
        OutputStream out = response.getOutputStream();
1802
        response.setStatus(200);
1803 5287 jones
        try {
1804
            localId = im.getLocalId(guid);
1805
        } catch (McdbDocNotFoundException e) {
1806 5657 berkley
            NotFound nf = new NotFound("1340", "Document with guid " + guid + " not found.");
1807
            response.setStatus(404);
1808
            serializeException(nf, out);
1809 5287 jones
        }
1810 5657 berkley
1811
        AuthToken token = new AuthToken(sessionId);
1812
        CrudService cs = CrudService.getInstance();
1813
        Identifier id = new Identifier();
1814
        id.setValue(guid);
1815
        try
1816
        {
1817
            System.out.println("Calling delete");
1818
            cs.delete(token, id);
1819 5673 berkley
            serializeServiceType(Identifier.class, id, out);
1820 5657 berkley
        }
1821
        catch (NotAuthorized e) {
1822
            response.setStatus(500);
1823
            serializeException(e, out);
1824
        } catch (InvalidToken e) {
1825
            response.setStatus(500);
1826
            serializeException(e, out);
1827
        } catch (ServiceFailure e) {
1828
            response.setStatus(500);
1829
            serializeException(e, out);
1830
        } catch (NotImplemented e) {
1831
            response.setStatus(500);
1832
            serializeException(e, out);
1833
        } catch (InvalidRequest e) {
1834
            response.setStatus(500);
1835
            serializeException(e, out);
1836
        } catch(NotFound e) {
1837
            response.setStatus(500);
1838
            serializeException(e, out);
1839 5673 berkley
        } catch(JiBXException e) {
1840
            response.setStatus(500);
1841
            serializeException(new ServiceFailure("1350", "JiBXException: " + e.getMessage()), out);
1842 5657 berkley
        }
1843 5211 jones
        out.close();
1844
    }
1845 5370 berkley
1846
    /**
1847
     * set the access perms on a document
1848
     * @throws IOException
1849
     */
1850 5424 berkley
    private void setaccess() throws Exception
1851 5370 berkley
    {
1852
        try
1853
        {
1854
            String guid = params.get("guid")[0];
1855
            Identifier id = new Identifier();
1856
            id.setValue(guid);
1857
            AuthToken token = new AuthToken(sessionId);
1858
            String principal = params.get("principal")[0];
1859
            String permission = params.get("permission")[0];
1860
            String permissionType = params.get("permissionType")[0];
1861
            String permissionOrder = params.get("permissionOrder")[0];
1862
            String setSystemMetadata = params.get("setsystemmetadata")[0];
1863 5424 berkley
            boolean ssm = false;
1864 5370 berkley
            if(setSystemMetadata.equals("true") || setSystemMetadata.equals("TRUE") ||
1865 5424 berkley
                    setSystemMetadata.equals("yes"))
1866
            {
1867
                ssm = true;
1868 5370 berkley
            }
1869 5424 berkley
            CrudService cs = CrudService.getInstance();
1870 5484 berkley
            //TODO: remove the setsystemmetadata param and set this so the systemmetadata always gets set
1871 5424 berkley
            cs.setAccess(token, id, principal, permission, permissionType, permissionOrder, ssm);
1872 5370 berkley
        }
1873
        catch(Exception e)
1874
        {
1875 5512 berkley
            response.setStatus(500);
1876 5370 berkley
            printError("Error setting access in ResourceHandler: " + e.getMessage(), response);
1877 5424 berkley
            throw e;
1878 5370 berkley
        }
1879
    }
1880 5211 jones
1881
    /**
1882
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
1883
     *
1884
     * @throws IOException
1885
     */
1886
    private void login() throws IOException {
1887
        PrintWriter out = response.getWriter();
1888 5515 berkley
        response.setStatus(200);
1889 5450 berkley
        response.setContentType("text/xml");
1890 5211 jones
        handler.handleLoginAction(out, params, request, response);
1891
        out.close();
1892
    }
1893
1894
    /**
1895
     * Earthgrid API > Authentication Service > Logout Function : calls MetacatHandler > handleLogoutAction
1896
     *
1897
     * @throws IOException
1898
     */
1899
    private void logout() throws IOException {
1900
        PrintWriter out = response.getWriter();
1901 5515 berkley
        response.setStatus(200);
1902 5450 berkley
        response.setContentType("text/xml");
1903 5211 jones
        handler.handleLogoutAction(out, params, request, response);
1904
        out.close();
1905
    }
1906
1907
    /**
1908
     * Prints xml response
1909
     * @param message Message to be displayed
1910
     * @param response Servlet response that xml message will be printed
1911
     * */
1912
    private void printError(String message, HttpServletResponse response) {
1913
        try {
1914 5512 berkley
            logMetacat.error("ResourceHandler: Printing error to servlet response: " + message);
1915 5211 jones
            PrintWriter out = response.getWriter();
1916
            response.setContentType("text/xml");
1917
            out.println("<?xml version=\"1.0\"?>");
1918
            out.println("<error>");
1919
            out.println(message);
1920
            out.println("</error>");
1921
            out.close();
1922
        } catch (IOException e) {
1923
            e.printStackTrace();
1924
        }
1925
    }
1926 5370 berkley
1927 5692 berkley
    /**
1928
     * serialize a D1 exception using jibx
1929
     * @param e
1930
     * @param out
1931
     */
1932 5319 jones
    private void serializeException(BaseException e, OutputStream out) {
1933
        // TODO: Use content negotiation to determine which return format to use
1934
        response.setContentType("text/xml");
1935
        response.setStatus(e.getCode());
1936 5512 berkley
1937
        logMetacat.error("ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
1938
        e.printStackTrace();
1939
1940 5319 jones
        try {
1941
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
1942
        } catch (IOException e1) {
1943
            logMetacat.error("Error writing exception to stream. "
1944
                    + e1.getMessage());
1945
        }
1946
    }
1947 5692 berkley
1948
    /**
1949
     * create a new ServiceMethod declaration
1950
     * @param name
1951
     * @param rest
1952
     * @param implemented
1953
     * @return
1954
     */
1955
    private ServiceMethod getServiceMethod(String name, String rest, boolean implemented)
1956
    {
1957
        ServiceMethod sm = new ServiceMethod();
1958
        sm.setImplemented(implemented);
1959
        sm.setName(name);
1960
        sm.setRest(rest);
1961
        return sm;
1962
    }
1963 5319 jones
1964 5211 jones
}