Project

General

Profile

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