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