Project

General

Profile

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