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