Project

General

Profile

1 5211 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              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 5370 berkley
import java.io.*;
26
import java.util.*;
27 5211 jones
28 5319 jones
import javax.mail.BodyPart;
29
import javax.mail.MessagingException;
30
import javax.mail.internet.MimeMultipart;
31 5211 jones
import javax.servlet.ServletContext;
32
import javax.servlet.http.HttpServletRequest;
33
import javax.servlet.http.HttpServletResponse;
34 5370 berkley
import java.text.DateFormat;
35 5428 berkley
import java.text.ParseException;
36 5391 berkley
import java.text.ParsePosition;
37
import java.text.SimpleDateFormat;
38 5211 jones
39 5391 berkley
40 5390 berkley
import org.apache.commons.httpclient.util.DateParser;
41 5299 jones
import org.apache.commons.io.IOUtils;
42 5211 jones
import org.apache.log4j.Logger;
43 5299 jones
import org.dataone.service.exceptions.BaseException;
44 5319 jones
import org.dataone.service.exceptions.IdentifierNotUnique;
45
import org.dataone.service.exceptions.InsufficientResources;
46
import org.dataone.service.exceptions.InvalidRequest;
47
import org.dataone.service.exceptions.InvalidSystemMetadata;
48
import org.dataone.service.exceptions.InvalidToken;
49
import org.dataone.service.exceptions.NotAuthorized;
50
import org.dataone.service.exceptions.NotImplemented;
51 5299 jones
import org.dataone.service.exceptions.ServiceFailure;
52 5319 jones
import org.dataone.service.exceptions.UnsupportedType;
53 5353 berkley
import org.dataone.service.exceptions.NotFound;
54 5370 berkley
import org.dataone.service.types.*;
55 5320 jones
import org.jibx.runtime.BindingDirectory;
56
import org.jibx.runtime.IBindingFactory;
57 5332 jones
import org.jibx.runtime.IMarshallingContext;
58 5320 jones
import org.jibx.runtime.IUnmarshallingContext;
59
import org.jibx.runtime.JiBXException;
60 5211 jones
61
import edu.ucsb.nceas.metacat.DBUtil;
62 5282 jones
import edu.ucsb.nceas.metacat.IdentifierManager;
63
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
64 5211 jones
import edu.ucsb.nceas.metacat.MetacatHandler;
65 5425 berkley
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
66 5299 jones
import edu.ucsb.nceas.metacat.dataone.CrudService;
67 5374 berkley
import edu.ucsb.nceas.metacat.service.SessionService;
68 5211 jones
import edu.ucsb.nceas.metacat.util.RequestUtil;
69
import edu.ucsb.nceas.metacat.util.SessionData;
70
71
/**
72
 *
73
 * Implements Earthgrid REST API to Metacat <br/><br/>
74
 *
75
 * <ul>
76
 * <li>
77
 * <h3> EarthGrid Query Service</h3>
78
 * <ul><li>
79
 * <h3>Get & Authenticated Get:</h3>
80
 * is equal to Metacat's read action and returns a data file having
81
 * the specified <doc-id> in the resource path. For authenticated Get service, a session id must be provided
82
 * in the query string. <br/><br/>
83
 *
84 5224 jones
 * <b>REST URL:</b>	<code>GET, [context-root]/object/[doc-id]?sessionid=[sessionid] </code><br/>
85 5211 jones
 * <b>Returns:</b> data file <br/><br/>
86
 * </li>
87
 *
88
 * <li>
89
 * <h3>Query & Authenticated Query:</h3>
90
 * Metacat's equivalent is squery action but this function
91
 * receives a Earthgrid query document and returns Earthgrid resultset document by transforming those documents
92
 * to Metacat's equivalents by the means of Metacat Implementation in Earthgrid library. For authenticated Query service
93
 * a session id must be provided in the query string. See Earthgrid (a.k.a. Ecogrid) project for XSD files of
94
 * query and resultset documents<br/><br/>
95
 *
96 5224 jones
 * <b>REST URL:</b>	<code>POST, [context-root]/object?sessionid=[sessionid]</code>    <br/>
97 5211 jones
 * <b>POST Data:</b> Earthgrid query document , Content-type: <code>text/xml</code><br/>
98
 * <b>Returns:</b> Earthgrid resultset document<br/><br/>
99
 *
100
 * </li>
101
 * </ul>
102
 *
103
 * </li>
104
 *
105
 * <li>
106
 * <h3> EarthGrid Authentication Service</h3>
107
 * <ul><li>
108
 * <h3>Login: </h3>
109
 * Receives username and password parameters in POST data and
110
 * returns SessionId (in XML format) or failure message and uses MetacatHandler's handleLoginAction function<br/><br/>
111
 *
112
 * <b>REST URL:</b> <code>POST, [context-root]/session?op=login</code> <br/>
113
 * <b>POST Data:</b> username=[username]&password=[password], Content-type: <code>application/x-www-form-urlencoded</code>
114
 * <b>Returns:</b> sessionId in XML format<br/><br/>
115
 * </li>
116
 *
117
 * <li>
118
 * <h3>Logout: </h3>
119
 * Receives session Id parameters in querystring and returns xml message, calls
120
 * MetacatHandler's handleLogoutAction function<br/><br/>
121
 *
122
 * <b>REST URL:</b>	<code>GET, [context-root]/session?op=logout&sessionid=[sessionid]</code>   <br/>
123
 * <b>Returns:</b> message in XML format<br/><br/>
124
 * </li>
125
 * </ul>
126
 *
127
 * <li>
128
 * <h3>EarthGrid Put Service</h3>
129
 *
130
 * <ul>
131
 * <li><h3>Update/Insert: </h3>
132
 * <br/>
133 5224 jones
 * <b>REST URL:</b>	<code>PUT, [context-root]/object/[doc-id]?op={update|insert}&sessionid=[sessionid]</code>   <br/>
134 5211 jones
 * <b>POST Data:</b> document object, Content-type: <code>text/xml</code><br/>
135
 * <b>Returns:</b> message in XML format<br/><br/>
136
 * </li>
137
 *
138
 * <li><h3>Delete: </h3>
139
 * <br/>
140 5224 jones
 * <b>REST URL:</b>	<code>DELETE, [context-root]/object/[doc-id]?sessionid=[sessionid]</code>   <br/>
141 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
142
 * </li>
143
144
 * </ul>
145
 * </li>
146
 *
147
 * <li>
148
 * <h3>EarthGrid Identifier Service</h3><br/>
149
 *
150
 * <ul>
151
 * <li><h3>isRegistered: </h3>		<br/>
152
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier/[doc-id]?op=isregistered</code>   <br/>
153
 * <b>Returns:</b> message in XML format<br/><br/>
154
 * </li>
155
156
 * <li><h3>getAllDocIds:</h3>		<br/>
157
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier?op=getalldocids</code>   <br/>
158
 * <b>Returns:</b> document id list in XML format<br/><br/>
159
 * </li>
160
 *
161
 * <li><h3>addLSID Function:</h3>
162
 * Metacat does not support this function 		<br/>
163
 * <b>REST URL:</b>	<code>PUT, [context-root]/identifier/[doc-id]</code>   <br/>
164
 * <b>Returns:</b> error message in XML format<br/><br/>
165
 * </li>
166
 *
167
 * <li><h3>getNextRevision:</h3>		<br/>
168
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier/[doc-id]?op=getnextrevision</code>   <br/>
169
 * <b>Returns:</b> message in XML format<br/><br/>
170
 * </li>
171
 *
172
 * <li><h3>getNextObject:</h3>		<br/>
173
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier?op=getnextobject&scope=[scope]</code>   <br/>
174
 * <b>Returns:</b> message in XML format<br/><br/>
175
 * </li>
176
 *
177
 * </li>
178
 * </ul>
179
 *
180
 */
181
public class ResourceHandler {
182
183
    /**HTTP Verb GET*/
184
    public static final byte GET = 1;
185
    /**HTTP Verb POST*/
186
    public static final byte POST = 2;
187
    /**HTTP Verb PUT*/
188
    public static final byte PUT = 3;
189
    /**HTTP Verb DELETE*/
190
    public static final byte DELETE = 4;
191
192
    /*
193
     * API Resources
194
     */
195 5224 jones
    private static final String RESOURCE_OBJECTS = "object";
196 5355 berkley
    private static final String RESOURCE_META = "meta";
197 5211 jones
    private static final String RESOURCE_SESSION = "session";
198
    private static final String RESOURCE_IDENTIFIER = "identifier";
199 5390 berkley
    private static final String RESOURCE_LOG = "log";
200 5211 jones
201
    /*
202
     * API Functions used as URL parameters
203
     */
204
    private static final String FUNCTION_KEYWORD = "op";
205
    private static final String FUNCTION_NAME_LOGIN = "login";
206
    private static final String FUNCTION_NAME_LOGOUT = "logout";
207 5370 berkley
    private static final String FUNCTION_NAME_SET_ACCESS = "setaccess";
208 5211 jones
    private static final String FUNCTION_NAME_ISREGISTERED = "isregistered";
209
    private static final String FUNCTION_NAME_GETALLDOCS = "getalldocids";
210
    private static final String FUNCTION_NAME_GETNEXTREV = "getnextrevision";
211
    private static final String FUNCTION_NAME_GETNEXTOBJ = "getnextobject";
212
    private static final String FUNCTION_NAME_INSERT = "insert";
213
    private static final String FUNCTION_NAME_UPDATE = "update";
214 5374 berkley
    private static final String FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA = "generatemissingsystemmetadata";
215 5211 jones
216 5428 berkley
    private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
217 5414 berkley
218 5211 jones
    private ServletContext servletContext;
219
    private Logger logMetacat;
220
    private MetacatHandler handler;
221
    private HttpServletRequest request;
222
    private HttpServletResponse response;
223
    private String username;
224
    private String password;
225
    private String sessionId;
226
    private String[] groupNames;
227
228
    private Hashtable<String, String[]> params;
229
230
    /**Initializes new instance by setting servlet context,request and response*/
231
    public ResourceHandler(ServletContext servletContext,
232
            HttpServletRequest request, HttpServletResponse response) {
233
        this.servletContext = servletContext;
234
        this.request = request;
235
        this.response = response;
236
    }
237
238
    /**
239
     * This function is called from REST APU servlet and handles each request to the servlet
240
     *
241
     * @param httpVerb (GET, POST, PUT or DELETE)
242
     */
243
    public void handle(byte httpVerb) {
244
        logMetacat = Logger.getLogger(ResourceHandler.class);
245
        try {
246
            String resource = request.getServletPath();
247 5355 berkley
            String verb = "";
248 5370 berkley
249 5424 berkley
            System.out.println("handling verb " + httpVerb + " request with resource " + resource);
250 5211 jones
            boolean status = false;
251 5424 berkley
            loadSessionData();
252 5211 jones
253
            if (resource != null) {
254 5446 jones
            	resource = request.getServletPath().substring(1);
255 5211 jones
256 5446 jones
            	params = new Hashtable<String, String[]>();
257
            	initParams();
258 5211 jones
259 5446 jones
            	Timer timer = new Timer();
260
            	handler = new MetacatHandler(timer);
261 5211 jones
262 5446 jones
            	if (resource.equals(RESOURCE_SESSION) &&
263
            			httpVerb == POST &&
264
            			params.get(FUNCTION_KEYWORD) != null) {
265
            		//System.out.println("function_keyword: " + params.get(FUNCTION_KEYWORD)[0]);
266
            		if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGIN)) {
267
            			login();
268
            			status = true;
269
            		} else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_LOGOUT)) {
270
            			logout();
271
            			status = true;
272
            		} else if (params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_SET_ACCESS)) {
273
            			setaccess();
274
            			status = true;
275
            			//System.out.println("done setting access");
276
            		}
277
            	} else if (resource.equals(RESOURCE_META)) {
278
            		if(params != null && params.get(FUNCTION_KEYWORD) != null &&
279
            				params.get(FUNCTION_KEYWORD)[0].equals(FUNCTION_NAME_GENERATE_MISSING_SYSTEM_METADATA))
280
            		{ //generate system metadata for any object that is
281
            			//a) not system metadata itself
282
            			//b) does not already have a system metadata id in the systemmetadata table
283
            			//c) not a BIN object (data)
284 5481 berkley
            		    //TODO: check if we need this anymore.  Might be superceded
285
            		    //by MetacatPopulator
286 5446 jones
            			generateMissingSystemMetadata();
287
            			status = true;
288
            		}
289
            		else
290
            		{
291
            			String objectId = request.getPathInfo();
292
            			if (objectId != null && objectId.length() > 1)
293
            			{
294
            				objectId = request.getPathInfo().substring(1);
295
            			}
296
            			getSystemMetadataObject(objectId);
297
            			status = true;
298
            		}
299 5211 jones
300 5446 jones
            	} else if (resource.equals(RESOURCE_OBJECTS)) {
301
            		logMetacat.debug("D1 Rest: Starting resource processing...");
302
            		loadSessionData();
303 5211 jones
304 5446 jones
            		String objectId = request.getPathInfo();
305
            		if (objectId != null && objectId.length() > 1)
306
            		{
307
            			objectId = request.getPathInfo().substring(1);
308
            		}
309
            		else
310
            		{
311
            			objectId = null;
312
            		}
313 5211 jones
314 5446 jones
            		logMetacat.debug("verb:" + httpVerb);
315 5211 jones
316 5446 jones
            		if (httpVerb == GET) {
317
            			getObject(objectId);
318
            			status = true;
319
            		} else if (httpVerb == POST) {
320
            			putObject(objectId, FUNCTION_NAME_INSERT);
321
            			status = true;
322
            		} else if (httpVerb == PUT) {
323
            			putObject(objectId, FUNCTION_NAME_UPDATE);
324
            			status = true;
325
            		} else if (httpVerb == DELETE) {
326
            			deleteObject(objectId);
327
            			status = true;
328
            		}
329 5211 jones
330 5446 jones
            	} else if (resource.equals(RESOURCE_IDENTIFIER)) {
331 5211 jones
332 5446 jones
            		String identifierId = request.getPathInfo();
333
            		if (identifierId != null && identifierId.length() > 1)
334
            			identifierId = request.getPathInfo().substring(1); //trim the slash
335 5211 jones
336 5446 jones
            		if (httpVerb == GET) {
337
            			String op = params.get(FUNCTION_KEYWORD)[0];
338
            			if (op.equals(FUNCTION_NAME_ISREGISTERED)) {
339
            				isRegistered(identifierId);
340
            				status = true;
341
            			} else if (op.equals(FUNCTION_NAME_GETALLDOCS)) {
342
            				getAllDocIds();
343
            				status = true;
344
            			} else if (op.equals(FUNCTION_NAME_GETNEXTREV)) {
345
            				getNextRevision(identifierId);
346
            				status = true;
347
            			} else if (op.equals(FUNCTION_NAME_GETNEXTOBJ)) {
348
            				getNextObject();
349
            				status = true;
350
            			}
351
352
            		} else if (httpVerb == PUT) {
353
            			//Earthgrid API > Identifier Service > addLSID Function
354 5512 berkley
            		    response.setStatus(501);
355 5446 jones
            			printError(
356
            					"This method is not supported by metacat.  To "
357
            					+ "add a new LSID, add a document to metacat.",
358
            					response);
359
            			status = true;
360
            		}
361
362
            	} else if (resource.equals(RESOURCE_LOG)) {
363
            		//handle log events
364
            		if(httpVerb == GET)
365
            		{
366
            			getLog();
367
            			status = true;
368
            		}
369
            		else
370
            		{
371 5481 berkley
            		    //change to D1 spec for specifying which http methods are allowed for a resource
372 5512 berkley
            		    response.setStatus(501);
373 5446 jones
            			printError("POST, PUT, DELETE is not supported for logs.", response);
374
            			status = true;
375
            		}
376
377
            	}
378
379
            	if (!status)
380 5512 berkley
            	{
381
            	    response.setStatus(400);
382 5446 jones
            		printError("Incorrect parameters!", response);
383 5512 berkley
            	}
384 5211 jones
            } else {
385 5512 berkley
                response.setStatus(400);
386 5446 jones
            	printError("Incorrect resource!", response);
387 5211 jones
            }
388
        } catch (Exception e) {
389 5446 jones
        	logMetacat.error(e.getMessage());
390
        	e.printStackTrace();
391 5211 jones
        }
392
    }
393 5374 berkley
394
    /**
395 5390 berkley
     * get the logs from the CrudService based on passed params.  Available
396
     * params are token, fromDate, toDate, event.  See
397
     * http://mule1.dataone.org/ArchitectureDocs/mn_api_crud.html#MN_crud.getLogRecords
398
     * for more info
399
     */
400
    private void getLog()
401
    {
402
        OutputStream out = null;
403
        try
404
        {
405
            out = response.getOutputStream();
406 5515 berkley
            response.setStatus(200);
407 5450 berkley
            response.setContentType("text/xml");
408 5390 berkley
            AuthToken token = new AuthToken(sessionId);
409
            String fromDateS = params.get("fromDate")[0];
410 5418 berkley
            System.out.println("param fromDateS: " + fromDateS);
411 5390 berkley
            Date fromDate = null;
412
            String toDateS = params.get("toDate")[0];
413 5418 berkley
            System.out.println("param toDateS: " + toDateS);
414 5390 berkley
            Date toDate = null;
415
            String eventS = params.get("event")[0];
416
            Event event = null;
417
            if(fromDateS != null)
418
            {
419 5429 berkley
                //fromDate = dateFormat.parse(fromDateS);
420
                fromDate = parseDateAndConvertToGMT(fromDateS);
421 5390 berkley
            }
422
            if(toDateS != null)
423
            {
424 5429 berkley
                //toDate = dateFormat.parse(toDateS);
425
                toDate = parseDateAndConvertToGMT(toDateS);
426 5390 berkley
            }
427
            if(eventS != null)
428
            {
429
                event = Event.convert(eventS);
430
            }
431 5418 berkley
            System.out.println("fromDate: " + fromDate + " toDate: " + toDate);
432 5395 berkley
433 5418 berkley
            System.out.println("calling crudservice.getLogRecords");
434 5390 berkley
            Log log = CrudService.getInstance().getLogRecords(token, fromDate, toDate, event);
435
            serializeServiceType(Log.class, log, out);
436
        }
437
        catch(Exception e)
438
        {
439
            String msg = "Could not get logs from CrudService: " + e.getMessage();
440
            ServiceFailure sf = new ServiceFailure("1490", msg);
441
            logMetacat.error(msg);
442
            e.printStackTrace();
443
            serializeException(sf, out);
444
        }
445
    }
446
447
    /**
448 5374 berkley
     *  copies request parameters to a hashtable which is given as argument to native metacathandler functions
449
     */
450
    private void initParams() {
451 5211 jones
452 5374 berkley
        String name = null;
453
        String[] value = null;
454
        Enumeration paramlist = request.getParameterNames();
455
        while (paramlist.hasMoreElements()) {
456
            name = (String) paramlist.nextElement();
457
            value = request.getParameterValues(name);
458
            params.put(name, value);
459
        }
460
    }
461
462 5211 jones
    /**
463 5374 berkley
     *
464
     * Load user details of metacat session from the request
465
     *
466
     */
467
    private void loadSessionData()
468
      throws Exception
469
    {
470
        SessionData sessionData = RequestUtil.getSessionData(request);
471
        try
472
        {
473
            username = null;
474
            password = null;
475
            groupNames = null;
476
            sessionId = null;
477
478
            boolean validSession = false;
479
            SessionService ss = SessionService.getInstance();
480 5410 berkley
            System.out.println("sessionData: " + sessionData);
481 5423 berkley
            if(sessionData == null)
482
            {
483
                username = "public";
484
                sessionId = "0";
485
                System.out.println("sessiondata is null.  Creating a public session.");
486
                return;
487
            }
488
489 5410 berkley
            System.out.println("username: " + sessionData.getUserName());
490
            System.out.println("sessionid: " + sessionData.getId());
491 5374 berkley
            //validate the session
492 5410 berkley
            if(ss.isSessionRegistered(sessionData.getId()) &&
493
               !(sessionData.getUserName().equals("public") || sessionData.getId().equals("0")))
494 5374 berkley
            {
495
                validSession = true;
496
            }
497
498
            if(validSession)
499
            {
500
                //if the session is valid, set these variables
501
                username = sessionData.getUserName();
502
                password = sessionData.getPassword();
503
                groupNames = sessionData.getGroupNames();
504
                sessionId = sessionData.getId();
505 5386 berkley
                System.out.println("setting sessionid to " + sessionId);
506
                System.out.println("username: " + username);
507 5374 berkley
            }
508
509
            //if the session is not valid or the username is null, set
510
            //username to public
511
            if (username == null)
512
            {
513 5386 berkley
                System.out.println("setting username to public.");
514 5374 berkley
                username = "public";
515
            }
516
        }
517
        catch(Exception e)
518
        {
519 5423 berkley
            e.printStackTrace();
520 5374 berkley
            throw new Exception("Could not load the session data: " + e.getMessage());
521
        }
522
    }
523
524
    /**
525
     * generate missing system metadata for any science metadata objects
526
     * that don't already have it. https://trac.dataone.org/ticket/591
527 5381 berkley
     *
528
     * called with POST meta/?op=generatemissingsystemmetadata
529 5374 berkley
     */
530
    private void generateMissingSystemMetadata()
531
    {
532 5381 berkley
        AuthToken token = new AuthToken(sessionId);
533
        CrudService.getInstance().generateMissingSystemMetadata(token);
534 5374 berkley
    }
535
536
    /**
537
     *  Earthgrid API > Identifier Service > isRegistered Function :
538
     *  calls MetacatHandler > handleIdIsRegisteredAction
539 5286 jones
     * @param guid
540 5211 jones
     * @throws IOException
541
     */
542 5286 jones
    private void isRegistered(String guid) throws IOException
543
    {
544
545
        // Look up the localId for this guid
546
        IdentifierManager im = IdentifierManager.getInstance();
547
        String localId = "";
548
        try {
549
            localId = im.getLocalId(guid);
550
        } catch (McdbDocNotFoundException e) {
551
            // TODO: Need to return the proper DataONE exception
552
        }
553
554
        params.put("docid", new String[] { localId });
555 5211 jones
        PrintWriter out = response.getWriter();
556 5515 berkley
        response.setStatus(200);
557 5450 berkley
        response.setContentType("text/xml");
558 5211 jones
        handler.handleIdIsRegisteredAction(out, params, response);
559
        out.close();
560
    }
561
562
    /**
563 5374 berkley
     * Earthgrid API > Identifier Service > getAllDocIds Function :
564
     * calls MetacatHandler > handleGetAllDocidsAction
565 5211 jones
     * @throws IOException
566
     */
567
    private void getAllDocIds() throws IOException {
568
        PrintWriter out = response.getWriter();
569 5515 berkley
        response.setStatus(200);
570 5450 berkley
        response.setContentType("text/xml");
571 5211 jones
        handler.handleGetAllDocidsAction(out, params, response);
572
        out.close();
573
    }
574
575
    /**
576 5374 berkley
     * Earthgrid API > Identifier Service > getNextRevision Function :
577
     * calls MetacatHandler > handleGetRevisionAndDocTypeAction
578 5286 jones
     * @param guid
579 5211 jones
     * @throws IOException
580
     */
581 5286 jones
    private void getNextRevision(String guid) throws IOException
582
    {
583
        params.put("docid", new String[] { guid });
584 5211 jones
        PrintWriter out = response.getWriter();
585 5515 berkley
        response.setStatus(200);
586 5450 berkley
        response.setContentType("text/xml");
587 5211 jones
        //handler.handleGetRevisionAndDocTypeAction(out, params);
588
589
        try {
590
            // Make sure there is a docid
591 5286 jones
            if (guid == null || guid.equals("")) {
592 5211 jones
                throw new Exception("User didn't specify docid!");
593 5286 jones
            }
594 5211 jones
595 5286 jones
            // Look up the localId for this guid
596
            IdentifierManager im = IdentifierManager.getInstance();
597
            String localId = "";
598
            try {
599
                localId = im.getLocalId(guid);
600
            } catch (McdbDocNotFoundException e) {
601
                // TODO: Need to return the proper DataONE exception
602
            }
603
604 5211 jones
            // Create a DBUtil object
605
            DBUtil dbutil = new DBUtil();
606
            // Get a rev and doctype
607
            String revAndDocType = dbutil
608 5286 jones
                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
609 5211 jones
            int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
610
611
            out.println("<?xml version=\"1.0\"?>");
612
            out.print("<next-revision>");
613
            out.print(revision);
614
            out.print("</next-revision>");
615
616
        } catch (Exception e) {
617
            // Handle exception
618 5512 berkley
            response.setStatus(500);
619 5211 jones
            out.println("<?xml version=\"1.0\"?>");
620
            out.println("<error>");
621
            out.println(e.getMessage());
622
            out.println("</error>");
623
        }
624
625
        out.close();
626
    }
627
628
    /**
629 5374 berkley
     * Earthgrid API > Identifier Service > getNextObject Function :
630
     * calls MetacatHandler > handleGetMaxDocidAction
631 5211 jones
     * @throws IOException
632
     */
633
    private void getNextObject() throws IOException {
634
        PrintWriter out = response.getWriter();
635 5515 berkley
        response.setStatus(200);
636 5450 berkley
        response.setContentType("text/xml");
637 5211 jones
        handler.handleGetMaxDocidAction(out, params, response);
638
        out.close();
639
    }
640
641
    /**
642 5299 jones
     * Implements REST version of DataONE CRUD API --> get
643 5282 jones
     * @param guid ID of data object to be read
644 5211 jones
     */
645 5450 berkley
    private void getObject(String guid) {
646
        CrudService cs = CrudService.getInstance();
647
        cs.setParamsFromRequest(request);
648
        AuthToken token = new AuthToken(sessionId);
649
        OutputStream out = null;
650
        try {
651
            out = response.getOutputStream();
652 5515 berkley
            response.setStatus(200);
653 5450 berkley
            response.setContentType("text/xml");
654
            if(guid != null)
655
            { //get a specific document
656
                Identifier id = new Identifier();
657
                id.setValue(guid);
658
                try
659
                {
660
                    if(token == null)
661
                    {
662
                        token = new AuthToken("Public");
663
                    }
664
                    InputStream data = cs.get(token, id);
665
                    IOUtils.copyLarge(data, response.getOutputStream());
666
                }
667
                catch(InvalidToken it)
668
                {
669
                    serializeException(it, out);
670
                }
671
                catch(ServiceFailure sf)
672
                {
673
                    serializeException(sf, out);
674
                }
675
                catch(NotAuthorized na)
676
                {
677
                    serializeException(na, out);
678
                }
679
                catch(NotFound nf)
680
                {
681
                    serializeException(nf, out);
682
                }
683
                catch(NotImplemented ni)
684
                {
685
                    serializeException(ni, out);
686
                }
687
                catch(Exception e)
688
                {
689
                    System.out.println("Error with Crud.get().  " +
690
                            "If this is an 'Exception producing data' error, " +
691
                            "go to CrudService.get() for better debugging.  " +
692
                            "Here's the error: " + e.getMessage());
693
                    e.printStackTrace();
694
                    ServiceFailure sf = new ServiceFailure("1030",
695
                            "IO Error in ResourceHandler.getObject: " + e.getMessage());
696
                    serializeException(sf, out);
697
                }
698
            }
699
            else
700
            { //call listObjects with specified params
701
                Date startTime = null;
702
                Date endTime = null;
703
                ObjectFormat objectFormat = null;
704
                boolean replicaStatus = false;
705
                int start = 0;
706 5481 berkley
                //TODO: make the max count into a const
707 5450 berkley
                int count = 1000;
708
                Enumeration paramlist = request.getParameterNames();
709
                while (paramlist.hasMoreElements())
710
                { //parse the params and make the crud call
711
                    String name = (String) paramlist.nextElement();
712
                    String[] value = (String[])request.getParameterValues(name);
713
                    /*for(int i=0; i<value.length; i++)
714
                    {
715
                        System.out.println("name: " + name + " value: " + value[i]);
716
                    }*/
717
                    if(name.equals("startTime") && value != null)
718
                    {
719
                        try
720
                        {
721
                          //startTime = dateFormat.parse(value[0]);
722
                            startTime = parseDateAndConvertToGMT(value[0]);
723
                        }
724
                        catch(Exception e)
725
                        {  //if we can't parse it, just don't use the startTime param
726
                            System.out.println("Could not parse startTime: " + value[0]);
727
                            startTime = null;
728
                        }
729
                    }
730
                    else if(name.equals("endTime") && value != null)
731
                    {
732
                        try
733
                        {
734
                          //endTime = dateFormat.parse(value[0]);
735
                            endTime = parseDateAndConvertToGMT(value[0]);
736
                        }
737
                        catch(Exception e)
738
                        {  //if we can't parse it, just don't use the endTime param
739
                            System.out.println("Could not parse endTime: " + value[0]);
740
                            endTime = null;
741
                        }
742
                    }
743
                    else if(name.equals("objectFormat") && value != null)
744
                    {
745
                        objectFormat = ObjectFormat.convert(value[0]);
746
                    }
747
                    else if(name.equals("replicaStatus") && value != null)
748
                    {
749
                        if(value != null &&
750
                           value.length > 0 &&
751
                           (value[0].equals("true") || value[0].equals("TRUE") || value[0].equals("YES")))
752
                        {
753
                            replicaStatus = true;
754
                        }
755
                    }
756
                    else if(name.equals("start") && value != null)
757
                    {
758
                        start = new Integer(value[0]).intValue();
759
                    }
760
                    else if(name.equals("count") && value != null)
761
                    {
762
                        count = new Integer(value[0]).intValue();
763
                    }
764
                }
765
                //make the crud call
766 5510 berkley
                System.out.println("token: " + token + " startTime: " + startTime +
767 5450 berkley
                        " endtime: " + endTime + " objectFormat: " +
768
                        objectFormat + " replicaStatus: " + replicaStatus +
769
                        " start: " + start + " count: " + count);
770 5510 berkley
771 5450 berkley
                ObjectList ol = cs.listObjects(token, startTime, endTime,
772
                        objectFormat, replicaStatus, start, count);
773
774
                StringReader sr = new StringReader(ol.toString());
775 5515 berkley
                out = response.getOutputStream();
776
                response.setStatus(200);
777 5450 berkley
                response.setContentType("text/xml");
778
                // Serialize and write it to the output stream
779
780
                try {
781
                    serializeServiceType(ObjectList.class, ol, out);
782
                } catch (JiBXException e) {
783
                    throw new ServiceFailure("1190", "Failed to serialize ObjectList: " + e.getMessage());
784
                }
785
            }
786
        } catch (BaseException e) {
787
                serializeException(e, out);
788
        } catch (IOException e) {
789
            e.printStackTrace();
790
            ServiceFailure sf = new ServiceFailure("1030",
791
                    "IO Error in ResourceHandler.getObject: " + e.getMessage());
792
            serializeException(sf, out);
793
        } catch(NumberFormatException ne) {
794
            InvalidRequest ir = new InvalidRequest("1030", "Invalid format for parameter: " + ne.getMessage());
795
            serializeException(ir, out);
796
        } catch (Exception e) {
797
            e.printStackTrace();
798
            ServiceFailure sf = new ServiceFailure("1030",
799
                    "Exception " + e.getClass().getName() + " raised while handling listObjects request: " +
800
                    e.getMessage());
801
            serializeException(sf, out);
802
        }
803
    }
804 5428 berkley
805
    /**
806
     * parse a date and return it in GMT if it ends with a 'Z'
807
     * @param date
808
     * @return
809
     * @throws ParseException
810
     */
811
    private Date parseDateAndConvertToGMT(String date) throws ParseException
812
    {
813 5429 berkley
        try
814
        {   //the format we want
815
            return dateFormat.parse(date);
816
        }
817
        catch(java.text.ParseException pe)
818
        {   //try another legacy format
819
            DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
820
            dateFormat2.setTimeZone(TimeZone.getTimeZone("GMT-0"));
821
            return dateFormat2.parse(date);
822
        }
823
824
        /*System.out.println("Parsing date " + date);
825 5428 berkley
        Date d = dateFormat.parse(date);
826
827
        if(date.endsWith("Z"))
828
        {
829
            Calendar lTime = Calendar.getInstance();
830
            lTime.setTime(d);
831
            Calendar zTime = Calendar.getInstance(TimeZone.getTimeZone("GMT-0"));
832
            zTime.set(Calendar.MONTH, lTime.get(Calendar.MONTH));
833
            zTime.set(Calendar.DATE, lTime.get(Calendar.DATE));
834
            zTime.set(Calendar.YEAR, lTime.get(Calendar.YEAR));
835
            zTime.set(Calendar.HOUR, lTime.get(Calendar.HOUR));
836
            zTime.set(Calendar.MINUTE, lTime.get(Calendar.MINUTE));
837
            zTime.set(Calendar.SECOND, lTime.get(Calendar.SECOND));
838
839
            System.out.println("date parsed to " + zTime.getTime());
840
            return zTime.getTime();
841
        }
842
843
        System.out.println("date parsed, but not converted. returned as " + d);
844 5429 berkley
        return d;*/
845 5428 berkley
    }
846 5211 jones
847
    /**
848 5332 jones
     * Implements REST version of DataONE CRUD API --> getSystemMetadata
849
     * @param guid ID of data object to be read
850
     */
851
    private void getSystemMetadataObject(String guid) {
852 5337 berkley
        CrudService cs = CrudService.getInstance();
853
        cs.setParamsFromRequest(request);
854 5386 berkley
        AuthToken token = new AuthToken(sessionId);
855 5332 jones
        OutputStream out = null;
856
        try {
857 5450 berkley
            response.setContentType("text/xml");
858 5515 berkley
            response.setStatus(200);
859 5332 jones
            out = response.getOutputStream();
860
            Identifier id = new Identifier();
861
            id.setValue(guid);
862
            SystemMetadata sysmeta = cs.getSystemMetadata(token, id);
863
864
            // Serialize and write it to the output stream
865
            try {
866 5481 berkley
                //TODO: look at the efficiency of this method.  The system metadata
867
                //is read from metacat (in CrudService) as xml, then serialized
868
                //to a SystemMetadat object, then returned here, then serizlized
869
                //back to XML to be sent to the response.
870 5390 berkley
                serializeServiceType(SystemMetadata.class, sysmeta, out);
871 5332 jones
            } catch (JiBXException e) {
872 5356 berkley
                throw new ServiceFailure("1190", "Failed to serialize SystemMetadata: " + e.getMessage());
873 5332 jones
            }
874
        } catch (BaseException e) {
875
                serializeException(e, out);
876
        } catch (IOException e) {
877 5414 berkley
            ServiceFailure sf = new ServiceFailure("1030",
878
                    "Error in ResourceHandler.getSystemMetadataObject: " + e.getMessage());
879 5332 jones
            serializeException(sf, out);
880
        } finally {
881
            IOUtils.closeQuietly(out);
882
        }
883
    }
884
885
    /**
886 5390 berkley
     * serialize an object of type to out
887
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
888
     * @param object the object to serialize
889
     * @param out the stream to serialize it to
890
     * @throws JiBXException
891
     */
892
    private void serializeServiceType(Class type, Object object, OutputStream out)
893
      throws JiBXException
894
    {
895
        IBindingFactory bfact = BindingDirectory.getFactory(type);
896
        IMarshallingContext mctx = bfact.createMarshallingContext();
897
        mctx.marshalDocument(object, "UTF-8", null, out);
898
    }
899
900
    /**
901
     * deserialize an object of type from is
902
     * @param type the class of the object to serialize (i.e. SystemMetadata.class)
903
     * @param is the stream to deserialize from
904
     * @throws JiBXException
905
     */
906
    private Object deserializeServiceType(Class type, InputStream is)
907
      throws JiBXException
908
    {
909
        IBindingFactory bfact = BindingDirectory.getFactory(type);
910
        IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
911
        Object o = (Object) uctx.unmarshalDocument(is, null);
912
        return o;
913
    }
914
915
    /**
916 5211 jones
     * Earthgrid API > Query Service > Query Function : translates ecogrid query document to metacat query
917
     * then calls DBQuery > createResultDocument function and then again translate resultset to ecogrid resultset
918
     *
919
     * NOTE:
920
     *      This is the only method that uses EcoGrid classes for its implementation.
921
     *      It does so because it takes an EcoGrid Query as input, and outputs an
922
     *      EcoGrid ResultSet document.  These documents are parsed by the auto-generated
923
     *      EcoGrid classes from axis, and so we link to them here rather than re-inventing them.
924
     *      This creates a circular dependency, because the Metacat classes are needed
925
     *      to build the EcoGrid implementation, and the EcoGrid jars are needed to build this query()
926
     *      method.  This circularity could be resolved by moving the EcoGrid classes
927
     *      to Metacat directly.  As we transition away from EcoGrid SOAP methods in
928
     *      favor of these REST interfaces, this circular dependency can be eliminated.
929
     *
930
     * @throws Exception
931
     */
932
    private void query() throws Exception {
933
        /*  This block commented out because of the EcoGrid circular dependency.
934
         *  For now, query will not be supported until the circularity can be
935 5286 jones
         *  resolved, probably by moving the ecogrid query syntax transformers
936 5211 jones
         *  directly into the Metacat codebase.  MBJ 2010-02-03
937
938
        try {
939
            EcogridQueryParser parser = new EcogridQueryParser(request
940
                    .getReader());
941
            parser.parseXML();
942
            QueryType queryType = parser.getEcogridQuery();
943
            EcogridJavaToMetacatJavaQueryTransformer queryTransformer =
944
                new EcogridJavaToMetacatJavaQueryTransformer();
945
            QuerySpecification metacatQuery = queryTransformer
946
                    .transform(queryType);
947
948
            DBQuery metacat = new DBQuery();
949
950
            boolean useXMLIndex = (new Boolean(PropertyService
951
                    .getProperty("database.usexmlindex"))).booleanValue();
952
            String xmlquery = "query"; // we don't care the query in resultset,
953
            // the query can be anything
954
            PrintWriter out = null; // we don't want metacat result, so set out null
955
956
            // parameter: queryspecification, user, group, usingIndexOrNot
957
            StringBuffer result = metacat.createResultDocument(xmlquery,
958
                    metacatQuery, out, username, groupNames, useXMLIndex);
959
960
            // create result set transfer
961
            String saxparser = PropertyService.getProperty("xml.saxparser");
962
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
963
                    new StringReader(result.toString()), saxparser, queryType
964
                            .getNamespace().get_value());
965
            ResultsetType records = metacatResultsetParser.getEcogridResult();
966
967
            System.out
968
                    .println(EcogridResultsetTransformer.toXMLString(records));
969
            response.setContentType("text/xml");
970
            out = response.getWriter();
971
            out.print(EcogridResultsetTransformer.toXMLString(records));
972
973
        } catch (Exception e) {
974
            e.printStackTrace();
975
        }*/
976
        response.setContentType("text/xml");
977 5512 berkley
        response.setStatus(501);
978 5211 jones
        PrintWriter out = response.getWriter();
979
        out.print("<error>Query operation not yet supported by Metacat.</error>");
980
        out.close();
981
    }
982 5319 jones
983 5394 berkley
    private String streamToString(InputStream is)
984
    throws IOException
985
    {
986
        byte b[] = new byte[1024];
987
        int numread = is.read(b, 0, 1024);
988
        String response = new String();
989
        while(numread != -1)
990
        {
991
            response += new String(b, 0, numread);
992
            numread = is.read(b, 0, 1024);
993
        }
994
        return response;
995
    }
996
997
    private InputStream stringToStream(String s)
998
    throws IOException
999
    {
1000
        ByteArrayInputStream bais = new ByteArrayInputStream(s.getBytes());
1001
        return bais;
1002
    }
1003
1004 5462 berkley
    /**
1005
     * process a mime multipart message
1006
     * @param is
1007
     * @return
1008
     */
1009
    private Hashtable processMMP(InputStream is)
1010
      throws IOException
1011
    {
1012 5481 berkley
        //TODO: verify that this is how the RFC for MMP should work
1013
        //SORTAHACK: Since mmp seems to have a bug where large object parts get truncated,
1014 5462 berkley
        //parse the stream here.  This has the disavantage of putting the
1015
        //stream into memory.
1016
        InputStream object = null;
1017
        InputStream sysmeta = null;
1018 5616 berkley
        String s = IOUtils.toString(is);
1019
        System.out.println("mime: " + s);
1020 5462 berkley
        //figure out what the boundary marker is
1021
        String searchString = "boundary=";
1022
        int searchStringIndex = s.indexOf(searchString);
1023
        String boundary = s.substring(searchStringIndex + searchString.length() + 1,
1024
                s.indexOf("\"", searchStringIndex + searchString.length() + 1));
1025
        boundary = "--" + boundary;
1026
        //System.out.println("boundary is " + boundary);
1027
1028
        //find the system metadata
1029
        searchString = "Content-Disposition: attachment; filename=systemmetadata";
1030
        searchStringIndex = s.indexOf(searchString);
1031 5616 berkley
        String sm = s.substring(searchStringIndex +
1032
                searchString.length() + 2,
1033
                s.indexOf(boundary, searchStringIndex));
1034
        sysmeta = new ByteArrayInputStream(sm.getBytes());
1035 5462 berkley
1036
        //find the object
1037
        searchString = "Content-Disposition: attachment; filename=object";
1038
        searchStringIndex = s.indexOf(searchString);
1039 5616 berkley
        String o = s.substring(searchStringIndex +
1040
                searchString.length() + 2,
1041
                s.indexOf(boundary, searchStringIndex));
1042
        object = new ByteArrayInputStream(o.getBytes());
1043 5462 berkley
1044
        Hashtable h = new Hashtable();
1045
        h.put("object", object);
1046
        h.put("systemmetadata", sysmeta);
1047 5616 berkley
1048
        System.out.println("o: \"" + o + "\"");
1049
        System.out.println("sm: \"" + sm + "\"");
1050 5462 berkley
        return h;
1051
    }
1052 5394 berkley
1053 5462 berkley
1054 5211 jones
    /**
1055
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction
1056
     *
1057 5319 jones
     * @param guid ID of data object to be inserted or updated
1058 5211 jones
     * @throws IOException
1059
     */
1060 5319 jones
    private void putObject(String guid, String action) {
1061
        logMetacat.debug("Entering putObject: " + guid + "/" + action);
1062
        OutputStream out = null;
1063
        try {
1064
            out = response.getOutputStream();
1065 5515 berkley
            response.setStatus(200);
1066 5450 berkley
            response.setContentType("text/xml");
1067 5319 jones
        } catch (IOException e1) {
1068
            logMetacat.error("Could not get the output stream for writing in putObject");
1069
        }
1070
        try {
1071 5353 berkley
1072
            // Read the incoming data from its Mime Multipart encoding
1073
            logMetacat.debug("Disassembling MIME multipart form");
1074
            InputStream object = null;
1075
            InputStream sysmeta = null;
1076 5394 berkley
1077 5462 berkley
            Hashtable parts = processMMP(request.getInputStream());
1078
            object = (InputStream)parts.get("object");
1079 5616 berkley
1080 5462 berkley
            sysmeta = (InputStream)parts.get("systemmetadata");
1081 5394 berkley
1082 5353 berkley
            if ( action.equals(FUNCTION_NAME_INSERT)) { //handle inserts
1083 5211 jones
1084 5319 jones
                // Check if the objectId exists
1085
                IdentifierManager im = IdentifierManager.getInstance();
1086
                if (im.identifierExists(guid)) {
1087 5356 berkley
                    throw new IdentifierNotUnique("1000", "Identifier is already in use: " + guid);
1088 5319 jones
                }
1089 5211 jones
1090 5376 berkley
                logMetacat.debug("Commence creation...");
1091
                IBindingFactory bfact =
1092
                    BindingDirectory.getFactory(SystemMetadata.class);
1093
                IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1094
                SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1095
1096
                CrudService cs = CrudService.getInstance();
1097 5386 berkley
                AuthToken token = new AuthToken(sessionId);
1098 5376 berkley
                cs.setParamsFromRequest(request);
1099
                Identifier id = new Identifier();
1100
                id.setValue(guid);
1101
                cs.create(token, id, object, m);
1102 5386 berkley
1103 5353 berkley
            } else if (action.equals(FUNCTION_NAME_UPDATE)) { //handle updates
1104
                IdentifierManager im = IdentifierManager.getInstance();
1105
                CrudService cs = CrudService.getInstance();
1106
                Identifier obsoletedGuid = new Identifier();
1107
                Identifier id = new Identifier();
1108
                id.setValue(guid);
1109 5386 berkley
                AuthToken token = new AuthToken(sessionId);
1110 5353 berkley
1111
                //do some checks
1112
                if(params.get("obsoletedGuid") == null)
1113
                {
1114 5356 berkley
                    throw new InvalidRequest("1202", "obsoletedGuid must be contained in the request parameters.");
1115 5353 berkley
                }
1116
                //get the obsoletedGuid
1117
                String[] obsGuidS = params.get("obsoletedGuid");
1118
                obsoletedGuid.setValue(obsGuidS[0]);
1119
1120
                if (!im.identifierExists(obsoletedGuid.getValue()))
1121
                {
1122 5356 berkley
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1123 5353 berkley
                }
1124
1125
1126
                logMetacat.debug("Commence update...");
1127
1128
                //get the systemmetadata
1129
                IBindingFactory bfact =
1130
                        BindingDirectory.getFactory(SystemMetadata.class);
1131
                    IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1132
                    SystemMetadata m = (SystemMetadata) uctx.unmarshalDocument(sysmeta, null);
1133
1134
                //do the update
1135
                try
1136
                {
1137
                    cs.setParamsFromRequest(request);
1138
                    Identifier rId = cs.update(token, id, object, obsoletedGuid, m);
1139
                }
1140
                catch(NotFound e)
1141
                {
1142 5356 berkley
                    throw new InvalidRequest("1202", "The guid you are trying to update does not exist.");
1143 5353 berkley
                }
1144
1145 5211 jones
            } else {
1146 5356 berkley
                throw new InvalidRequest("1000", "Operation must be create or update.");
1147 5211 jones
            }
1148 5319 jones
        } catch (NotAuthorized e) {
1149
            serializeException(e, out);
1150
        } catch (InvalidToken e) {
1151
            serializeException(e, out);
1152
        } catch (ServiceFailure e) {
1153
            serializeException(e, out);
1154
        } catch (IdentifierNotUnique e) {
1155
            serializeException(e, out);
1156
        } catch (UnsupportedType e) {
1157
            serializeException(e, out);
1158
        } catch (InsufficientResources e) {
1159
            serializeException(e, out);
1160
        } catch (InvalidSystemMetadata e) {
1161
            serializeException(e, out);
1162
        } catch (NotImplemented e) {
1163
            serializeException(e, out);
1164
        } catch (InvalidRequest e) {
1165
            serializeException(e, out);
1166 5394 berkley
        } /*catch (MessagingException e) {
1167 5356 berkley
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1168 5319 jones
            serializeException(sf, out);
1169 5394 berkley
        }*/ catch (IOException e) {
1170 5356 berkley
            ServiceFailure sf = new ServiceFailure("1000", e.getMessage());
1171 5319 jones
            serializeException(sf, out);
1172 5320 jones
        } catch (JiBXException e) {
1173
            e.printStackTrace(System.out);
1174 5356 berkley
            InvalidSystemMetadata ism = new InvalidSystemMetadata("1080", e.getMessage());
1175 5320 jones
            serializeException(ism, out);
1176 5211 jones
        }
1177
    }
1178
1179
    /**
1180
     * Earthgrid API > Put Service > Delete Function : calls MetacatHandler > handleDeleteAction
1181
     *
1182 5287 jones
     * @param guid ID of data object to be deleted
1183 5211 jones
     * @throws IOException
1184
     */
1185 5287 jones
    private void deleteObject(String guid) throws IOException
1186
    {
1187
        // Look up the localId for this global identifier
1188
        IdentifierManager im = IdentifierManager.getInstance();
1189
        String localId = "";
1190
        try {
1191
            localId = im.getLocalId(guid);
1192
        } catch (McdbDocNotFoundException e) {
1193
            // TODO: Need to return the proper DataONE exception
1194
        }
1195
1196
        params.put("docid", new String[] { localId });
1197 5211 jones
        PrintWriter out = response.getWriter();
1198 5515 berkley
        response.setStatus(200);
1199 5450 berkley
        response.setContentType("text/xml");
1200 5211 jones
        handler.handleDeleteAction(out, params, request, response, username,
1201
                groupNames);
1202
        out.close();
1203
    }
1204 5370 berkley
1205
    /**
1206
     * set the access perms on a document
1207
     * @throws IOException
1208
     */
1209 5424 berkley
    private void setaccess() throws Exception
1210 5370 berkley
    {
1211
        try
1212
        {
1213
            String guid = params.get("guid")[0];
1214
            Identifier id = new Identifier();
1215
            id.setValue(guid);
1216
            AuthToken token = new AuthToken(sessionId);
1217
            String principal = params.get("principal")[0];
1218
            String permission = params.get("permission")[0];
1219
            String permissionType = params.get("permissionType")[0];
1220
            String permissionOrder = params.get("permissionOrder")[0];
1221
            String setSystemMetadata = params.get("setsystemmetadata")[0];
1222 5424 berkley
            boolean ssm = false;
1223 5370 berkley
            if(setSystemMetadata.equals("true") || setSystemMetadata.equals("TRUE") ||
1224 5424 berkley
                    setSystemMetadata.equals("yes"))
1225
            {
1226
                ssm = true;
1227 5370 berkley
            }
1228 5424 berkley
            CrudService cs = CrudService.getInstance();
1229 5484 berkley
            //TODO: remove the setsystemmetadata param and set this so the systemmetadata always gets set
1230 5424 berkley
            cs.setAccess(token, id, principal, permission, permissionType, permissionOrder, ssm);
1231 5370 berkley
        }
1232
        catch(Exception e)
1233
        {
1234 5512 berkley
            response.setStatus(500);
1235 5370 berkley
            printError("Error setting access in ResourceHandler: " + e.getMessage(), response);
1236 5424 berkley
            throw e;
1237 5370 berkley
        }
1238
    }
1239 5211 jones
1240
    /**
1241
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
1242
     *
1243
     * @throws IOException
1244
     */
1245
    private void login() throws IOException {
1246
        PrintWriter out = response.getWriter();
1247 5515 berkley
        response.setStatus(200);
1248 5450 berkley
        response.setContentType("text/xml");
1249 5211 jones
        handler.handleLoginAction(out, params, request, response);
1250
        out.close();
1251
    }
1252
1253
    /**
1254
     * Earthgrid API > Authentication Service > Logout Function : calls MetacatHandler > handleLogoutAction
1255
     *
1256
     * @throws IOException
1257
     */
1258
    private void logout() throws IOException {
1259
        PrintWriter out = response.getWriter();
1260 5515 berkley
        response.setStatus(200);
1261 5450 berkley
        response.setContentType("text/xml");
1262 5211 jones
        handler.handleLogoutAction(out, params, request, response);
1263
        out.close();
1264
    }
1265
1266
    /**
1267
     * Prints xml response
1268
     * @param message Message to be displayed
1269
     * @param response Servlet response that xml message will be printed
1270
     * */
1271
    private void printError(String message, HttpServletResponse response) {
1272
        try {
1273 5512 berkley
            logMetacat.error("ResourceHandler: Printing error to servlet response: " + message);
1274 5211 jones
            PrintWriter out = response.getWriter();
1275
            response.setContentType("text/xml");
1276
            out.println("<?xml version=\"1.0\"?>");
1277
            out.println("<error>");
1278
            out.println(message);
1279
            out.println("</error>");
1280
            out.close();
1281
        } catch (IOException e) {
1282
            e.printStackTrace();
1283
        }
1284
    }
1285 5370 berkley
1286 5319 jones
    private void serializeException(BaseException e, OutputStream out) {
1287
        // TODO: Use content negotiation to determine which return format to use
1288
        response.setContentType("text/xml");
1289
        response.setStatus(e.getCode());
1290 5512 berkley
1291
        logMetacat.error("ResourceHandler: Serializing exception with code " + e.getCode() + ": " + e.getMessage());
1292
        e.printStackTrace();
1293
1294 5319 jones
        try {
1295
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
1296
        } catch (IOException e1) {
1297
            logMetacat.error("Error writing exception to stream. "
1298
                    + e1.getMessage());
1299
        }
1300
    }
1301
1302 5211 jones
}