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