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