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
import java.io.BufferedReader;
26 5319 jones
import java.io.File;
27
import java.io.FileNotFoundException;
28
import java.io.FileOutputStream;
29 5211 jones
import java.io.IOException;
30 5299 jones
import java.io.InputStream;
31 5319 jones
import java.io.OutputStream;
32 5211 jones
import java.io.PrintWriter;
33
import java.util.Enumeration;
34
import java.util.Hashtable;
35
import java.util.Timer;
36
37 5319 jones
import javax.mail.BodyPart;
38
import javax.mail.MessagingException;
39
import javax.mail.internet.MimeMultipart;
40 5211 jones
import javax.servlet.ServletContext;
41
import javax.servlet.http.HttpServletRequest;
42
import javax.servlet.http.HttpServletResponse;
43
44 5299 jones
import org.apache.commons.io.IOUtils;
45 5211 jones
import org.apache.log4j.Logger;
46 5299 jones
import org.dataone.service.exceptions.BaseException;
47 5319 jones
import org.dataone.service.exceptions.IdentifierNotUnique;
48
import org.dataone.service.exceptions.InsufficientResources;
49
import org.dataone.service.exceptions.InvalidRequest;
50
import org.dataone.service.exceptions.InvalidSystemMetadata;
51
import org.dataone.service.exceptions.InvalidToken;
52
import org.dataone.service.exceptions.NotAuthorized;
53
import org.dataone.service.exceptions.NotImplemented;
54 5299 jones
import org.dataone.service.exceptions.ServiceFailure;
55 5319 jones
import org.dataone.service.exceptions.UnsupportedType;
56 5299 jones
import org.dataone.service.types.AuthToken;
57
import org.dataone.service.types.IdentifierType;
58 5319 jones
import org.dataone.service.types.SystemMetadata;
59
import org.exolab.castor.jdo.conf.DataSource;
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 5299 jones
import edu.ucsb.nceas.metacat.dataone.CrudService;
66 5211 jones
import edu.ucsb.nceas.metacat.util.RequestUtil;
67
import edu.ucsb.nceas.metacat.util.SessionData;
68
69
/**
70
 *
71
 * Implements Earthgrid REST API to Metacat <br/><br/>
72
 *
73
 * <ul>
74
 * <li>
75
 * <h3> EarthGrid Query Service</h3>
76
 * <ul><li>
77
 * <h3>Get & Authenticated Get:</h3>
78
 * is equal to Metacat's read action and returns a data file having
79
 * the specified <doc-id> in the resource path. For authenticated Get service, a session id must be provided
80
 * in the query string. <br/><br/>
81
 *
82 5224 jones
 * <b>REST URL:</b>	<code>GET, [context-root]/object/[doc-id]?sessionid=[sessionid] </code><br/>
83 5211 jones
 * <b>Returns:</b> data file <br/><br/>
84
 * </li>
85
 *
86
 * <li>
87
 * <h3>Query & Authenticated Query:</h3>
88
 * Metacat's equivalent is squery action but this function
89
 * receives a Earthgrid query document and returns Earthgrid resultset document by transforming those documents
90
 * to Metacat's equivalents by the means of Metacat Implementation in Earthgrid library. For authenticated Query service
91
 * a session id must be provided in the query string. See Earthgrid (a.k.a. Ecogrid) project for XSD files of
92
 * query and resultset documents<br/><br/>
93
 *
94 5224 jones
 * <b>REST URL:</b>	<code>POST, [context-root]/object?sessionid=[sessionid]</code>    <br/>
95 5211 jones
 * <b>POST Data:</b> Earthgrid query document , Content-type: <code>text/xml</code><br/>
96
 * <b>Returns:</b> Earthgrid resultset document<br/><br/>
97
 *
98
 * </li>
99
 * </ul>
100
 *
101
 * </li>
102
 *
103
 * <li>
104
 * <h3> EarthGrid Authentication Service</h3>
105
 * <ul><li>
106
 * <h3>Login: </h3>
107
 * Receives username and password parameters in POST data and
108
 * returns SessionId (in XML format) or failure message and uses MetacatHandler's handleLoginAction function<br/><br/>
109
 *
110
 * <b>REST URL:</b> <code>POST, [context-root]/session?op=login</code> <br/>
111
 * <b>POST Data:</b> username=[username]&password=[password], Content-type: <code>application/x-www-form-urlencoded</code>
112
 * <b>Returns:</b> sessionId in XML format<br/><br/>
113
 * </li>
114
 *
115
 * <li>
116
 * <h3>Logout: </h3>
117
 * Receives session Id parameters in querystring and returns xml message, calls
118
 * MetacatHandler's handleLogoutAction function<br/><br/>
119
 *
120
 * <b>REST URL:</b>	<code>GET, [context-root]/session?op=logout&sessionid=[sessionid]</code>   <br/>
121
 * <b>Returns:</b> message in XML format<br/><br/>
122
 * </li>
123
 * </ul>
124
 *
125
 * <li>
126
 * <h3>EarthGrid Put Service</h3>
127
 *
128
 * <ul>
129
 * <li><h3>Update/Insert: </h3>
130
 * <br/>
131 5224 jones
 * <b>REST URL:</b>	<code>PUT, [context-root]/object/[doc-id]?op={update|insert}&sessionid=[sessionid]</code>   <br/>
132 5211 jones
 * <b>POST Data:</b> document object, Content-type: <code>text/xml</code><br/>
133
 * <b>Returns:</b> message in XML format<br/><br/>
134
 * </li>
135
 *
136
 * <li><h3>Delete: </h3>
137
 * <br/>
138 5224 jones
 * <b>REST URL:</b>	<code>DELETE, [context-root]/object/[doc-id]?sessionid=[sessionid]</code>   <br/>
139 5211 jones
 * <b>Returns:</b> message in XML format<br/><br/>
140
 * </li>
141
142
 * </ul>
143
 * </li>
144
 *
145
 * <li>
146
 * <h3>EarthGrid Identifier Service</h3><br/>
147
 *
148
 * <ul>
149
 * <li><h3>isRegistered: </h3>		<br/>
150
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier/[doc-id]?op=isregistered</code>   <br/>
151
 * <b>Returns:</b> message in XML format<br/><br/>
152
 * </li>
153
154
 * <li><h3>getAllDocIds:</h3>		<br/>
155
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier?op=getalldocids</code>   <br/>
156
 * <b>Returns:</b> document id list in XML format<br/><br/>
157
 * </li>
158
 *
159
 * <li><h3>addLSID Function:</h3>
160
 * Metacat does not support this function 		<br/>
161
 * <b>REST URL:</b>	<code>PUT, [context-root]/identifier/[doc-id]</code>   <br/>
162
 * <b>Returns:</b> error message in XML format<br/><br/>
163
 * </li>
164
 *
165
 * <li><h3>getNextRevision:</h3>		<br/>
166
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier/[doc-id]?op=getnextrevision</code>   <br/>
167
 * <b>Returns:</b> message in XML format<br/><br/>
168
 * </li>
169
 *
170
 * <li><h3>getNextObject:</h3>		<br/>
171
 * <b>REST URL:</b>	<code>GET, [context-root]/identifier?op=getnextobject&scope=[scope]</code>   <br/>
172
 * <b>Returns:</b> message in XML format<br/><br/>
173
 * </li>
174
 *
175
 * </li>
176
 * </ul>
177
 *
178
 */
179
public class ResourceHandler {
180
181
    /**HTTP Verb GET*/
182
    public static final byte GET = 1;
183
    /**HTTP Verb POST*/
184
    public static final byte POST = 2;
185
    /**HTTP Verb PUT*/
186
    public static final byte PUT = 3;
187
    /**HTTP Verb DELETE*/
188
    public static final byte DELETE = 4;
189
190
    /*
191
     * API Resources
192
     */
193 5224 jones
    private static final String RESOURCE_OBJECTS = "object";
194 5211 jones
    private static final String RESOURCE_SESSION = "session";
195
    private static final String RESOURCE_IDENTIFIER = "identifier";
196
197
    /*
198
     * API Functions used as URL parameters
199
     */
200
    private static final String FUNCTION_KEYWORD = "op";
201
    private static final String FUNCTION_NAME_LOGIN = "login";
202
    private static final String FUNCTION_NAME_LOGOUT = "logout";
203
    private static final String FUNCTION_NAME_ISREGISTERED = "isregistered";
204
    private static final String FUNCTION_NAME_GETALLDOCS = "getalldocids";
205
    private static final String FUNCTION_NAME_GETNEXTREV = "getnextrevision";
206
    private static final String FUNCTION_NAME_GETNEXTOBJ = "getnextobject";
207
    private static final String FUNCTION_NAME_INSERT = "insert";
208
    private static final String FUNCTION_NAME_UPDATE = "update";
209
210
    private ServletContext servletContext;
211
    private Logger logMetacat;
212
    private MetacatHandler handler;
213
    private HttpServletRequest request;
214
    private HttpServletResponse response;
215
    private String username;
216
    private String password;
217
    private String sessionId;
218
    private String[] groupNames;
219
220
    private Hashtable<String, String[]> params;
221
222
    /**Initializes new instance by setting servlet context,request and response*/
223
    public ResourceHandler(ServletContext servletContext,
224
            HttpServletRequest request, HttpServletResponse response) {
225
        this.servletContext = servletContext;
226
        this.request = request;
227
        this.response = response;
228
    }
229
230
    /**
231
     *  copies request parameters to a hashtable which is given as argument to native metacathandler functions
232
     */
233
    private void initParams() {
234
235
        String name = null;
236
        String[] value = null;
237
        Enumeration paramlist = request.getParameterNames();
238
        while (paramlist.hasMoreElements()) {
239
            name = (String) paramlist.nextElement();
240
            value = request.getParameterValues(name);
241
            params.put(name, value);
242
        }
243
244
    }
245
246
    /**
247
     *
248
     * Load user details of metacat session from the request
249
     *
250
     */
251
    private void loadSessionData() {
252
        SessionData sessionData = RequestUtil.getSessionData(request);
253
254 5286 jones
        // TODO: validate the session before allowing these values to be set
255 5211 jones
        username = sessionData.getUserName();
256
        password = sessionData.getPassword();
257
        groupNames = sessionData.getGroupNames();
258
        sessionId = sessionData.getId();
259
260 5286 jones
        if (username == null) {
261 5211 jones
            username = "public";
262 5286 jones
        }
263 5211 jones
    }
264
265
    /**
266
     * This function is called from REST APU servlet and handles each request to the servlet
267
     *
268
     * @param httpVerb (GET, POST, PUT or DELETE)
269
     */
270
    public void handle(byte httpVerb) {
271
272
        logMetacat = Logger.getLogger(ResourceHandler.class);
273
        try {
274
            String resource = request.getServletPath();
275
276
            boolean status = false;
277
278
            if (resource != null) {
279
                resource = request.getServletPath().substring(1);
280
                System.out.println("accessing resource: " + resource);
281
282
                params = new Hashtable<String, String[]>();
283
                initParams();
284
285
                Timer timer = new Timer();
286
                handler = new MetacatHandler(servletContext, timer);
287
288
                if (resource.equals(RESOURCE_SESSION) && httpVerb == POST
289
                        && params.get(FUNCTION_KEYWORD) != null) {
290
                    if (params.get(FUNCTION_KEYWORD)[0]
291
                            .equals(FUNCTION_NAME_LOGIN)) {
292
                        login();
293
                        status = true;
294
                    } else if (params.get(FUNCTION_KEYWORD)[0]
295
                            .equals(FUNCTION_NAME_LOGOUT)) {
296
                        logout();
297
                        status = true;
298
                    }
299
                } else if (resource.equals(RESOURCE_OBJECTS)) {
300 5319 jones
                    logMetacat.debug("D1 Rest: Starting resource processing...");
301 5211 jones
                    loadSessionData();
302
303
                    String objectId = request.getPathInfo();
304
                    if (objectId != null && objectId.length() > 1)
305
                        objectId = request.getPathInfo().substring(1); //trim the slash
306 5319 jones
                    logMetacat.debug("Processing objectId: " + objectId);
307
                    logMetacat.debug("verb:" + httpVerb);
308 5211 jones
309 5319 jones
                    logMetacat.debug("objectId:" + objectId);
310 5211 jones
311
                    if (httpVerb == GET) {
312
                        getObject(objectId);
313
                        status = true;
314
                    } else if (httpVerb == POST) {
315 5319 jones
                        putObject(objectId, FUNCTION_NAME_INSERT);
316 5211 jones
                        status = true;
317
                    } else if (httpVerb == PUT) {
318 5319 jones
                        putObject(objectId, FUNCTION_NAME_UPDATE);
319 5211 jones
                        status = true;
320
                    } else if (httpVerb == DELETE) {
321
                        deleteObject(objectId);
322
                        status = true;
323
                    }
324
325
                } else if (resource.equals(RESOURCE_IDENTIFIER)) {
326
327
                    String identifierId = request.getPathInfo();
328
                    if (identifierId != null && identifierId.length() > 1)
329
                        identifierId = request.getPathInfo().substring(1); //trim the slash
330
331
                    System.out.println("identifierId:" + identifierId);
332
333
                    if (httpVerb == GET) {
334
                        String op = params.get(FUNCTION_KEYWORD)[0];
335
                        System.out.println("op:" + op);
336
                        if (op.equals(FUNCTION_NAME_ISREGISTERED)) {
337
                            isRegistered(identifierId);
338
                            status = true;
339
                        } else if (op.equals(FUNCTION_NAME_GETALLDOCS)) {
340
                            getAllDocIds();
341
                            status = true;
342
                        } else if (op.equals(FUNCTION_NAME_GETNEXTREV)) {
343
                            getNextRevision(identifierId);
344
                            status = true;
345
                        } else if (op.equals(FUNCTION_NAME_GETNEXTOBJ)) {
346
                            getNextObject();
347
                            status = true;
348
                        }
349
350
                    } else if (httpVerb == PUT) {
351
                        //Earthgrid API > Identifier Service > addLSID Function
352
                        printError(
353
                                "This method is not supported by metacat.  To "
354
                                        + "add a new LSID, add a document to metacat.",
355
                                response);
356
                        status = true;
357
                    }
358
359
                }
360
                if (!status)
361
                    printError("Incorrect parameters!", response);
362
            } else {
363
                printError("Incorrect resource!", response);
364
            }
365
        } catch (Exception e) {
366
            logMetacat.error(e.getMessage());
367
            e.printStackTrace();
368
        }
369
    }
370
371
    /**
372
     *  Earthgrid API > Identifier Service > isRegistered Function : calls MetacatHandler > handleIdIsRegisteredAction
373 5286 jones
     * @param guid
374 5211 jones
     * @throws IOException
375
     */
376 5286 jones
    private void isRegistered(String guid) throws IOException
377
    {
378
379
        // Look up the localId for this guid
380
        IdentifierManager im = IdentifierManager.getInstance();
381
        String localId = "";
382
        try {
383
            localId = im.getLocalId(guid);
384
        } catch (McdbDocNotFoundException e) {
385
            // TODO: Need to return the proper DataONE exception
386
        }
387
388
        params.put("docid", new String[] { localId });
389 5211 jones
        PrintWriter out = response.getWriter();
390
        handler.handleIdIsRegisteredAction(out, params, response);
391
        out.close();
392
    }
393
394
    /**
395
     * Earthgrid API > Identifier Service > getAllDocIds Function : calls MetacatHandler > handleGetAllDocidsAction
396
     * @throws IOException
397
     */
398
    private void getAllDocIds() throws IOException {
399
        PrintWriter out = response.getWriter();
400
        handler.handleGetAllDocidsAction(out, params, response);
401
        out.close();
402
    }
403
404
    /**
405
     * Earthgrid API > Identifier Service > getNextRevision Function : calls MetacatHandler > handleGetRevisionAndDocTypeAction
406 5286 jones
     * @param guid
407 5211 jones
     * @throws IOException
408
     */
409 5286 jones
    private void getNextRevision(String guid) throws IOException
410
    {
411
        params.put("docid", new String[] { guid });
412 5211 jones
        PrintWriter out = response.getWriter();
413
        //handler.handleGetRevisionAndDocTypeAction(out, params);
414
415
        try {
416
            // Make sure there is a docid
417 5286 jones
            if (guid == null || guid.equals("")) {
418 5211 jones
                throw new Exception("User didn't specify docid!");
419 5286 jones
            }
420 5211 jones
421 5286 jones
            // Look up the localId for this guid
422
            IdentifierManager im = IdentifierManager.getInstance();
423
            String localId = "";
424
            try {
425
                localId = im.getLocalId(guid);
426
            } catch (McdbDocNotFoundException e) {
427
                // TODO: Need to return the proper DataONE exception
428
            }
429
430 5211 jones
            // Create a DBUtil object
431
            DBUtil dbutil = new DBUtil();
432
            // Get a rev and doctype
433
            String revAndDocType = dbutil
434 5286 jones
                    .getCurrentRevisionAndDocTypeForGivenDocument(localId);
435 5211 jones
            int revision = Integer.parseInt(revAndDocType.split(";")[0]) + 1;
436
437
            out.println("<?xml version=\"1.0\"?>");
438
            out.print("<next-revision>");
439
            out.print(revision);
440
            out.print("</next-revision>");
441
442
        } catch (Exception e) {
443
            // Handle exception
444
            out.println("<?xml version=\"1.0\"?>");
445
            out.println("<error>");
446
            out.println(e.getMessage());
447
            out.println("</error>");
448
        }
449
450
        out.close();
451
    }
452
453
    /**
454
     * Earthgrid API > Identifier Service > getNextObject Function : calls MetacatHandler > handleGetMaxDocidAction
455
     * @throws IOException
456
     */
457
    private void getNextObject() throws IOException {
458
        PrintWriter out = response.getWriter();
459
        handler.handleGetMaxDocidAction(out, params, response);
460
        out.close();
461
    }
462
463
    /**
464 5299 jones
     * Implements REST version of DataONE CRUD API --> get
465 5282 jones
     * @param guid ID of data object to be read
466 5211 jones
     */
467 5282 jones
    private void getObject(String guid) {
468 5299 jones
        CrudService cs = new CrudService(servletContext, request, response);
469
        AuthToken token = null;
470 5319 jones
        OutputStream out = null;
471 5282 jones
        try {
472 5319 jones
            out = response.getOutputStream();
473 5299 jones
            InputStream data = cs.get(token, new IdentifierType(guid));
474
            IOUtils.copyLarge(data, response.getOutputStream());
475
        } catch (BaseException e) {
476 5319 jones
                serializeException(e, out);
477 5299 jones
        } catch (IOException e) {
478
            ServiceFailure sf = new ServiceFailure(1030, e.getMessage());
479 5319 jones
            serializeException(sf, out);
480 5282 jones
        }
481 5211 jones
    }
482
483
    /**
484
     * Earthgrid API > Query Service > Query Function : translates ecogrid query document to metacat query
485
     * then calls DBQuery > createResultDocument function and then again translate resultset to ecogrid resultset
486
     *
487
     * NOTE:
488
     *      This is the only method that uses EcoGrid classes for its implementation.
489
     *      It does so because it takes an EcoGrid Query as input, and outputs an
490
     *      EcoGrid ResultSet document.  These documents are parsed by the auto-generated
491
     *      EcoGrid classes from axis, and so we link to them here rather than re-inventing them.
492
     *      This creates a circular dependency, because the Metacat classes are needed
493
     *      to build the EcoGrid implementation, and the EcoGrid jars are needed to build this query()
494
     *      method.  This circularity could be resolved by moving the EcoGrid classes
495
     *      to Metacat directly.  As we transition away from EcoGrid SOAP methods in
496
     *      favor of these REST interfaces, this circular dependency can be eliminated.
497
     *
498
     * @throws Exception
499
     */
500
    private void query() throws Exception {
501
        /*  This block commented out because of the EcoGrid circular dependency.
502
         *  For now, query will not be supported until the circularity can be
503 5286 jones
         *  resolved, probably by moving the ecogrid query syntax transformers
504 5211 jones
         *  directly into the Metacat codebase.  MBJ 2010-02-03
505
506
        try {
507
            EcogridQueryParser parser = new EcogridQueryParser(request
508
                    .getReader());
509
            parser.parseXML();
510
            QueryType queryType = parser.getEcogridQuery();
511
            EcogridJavaToMetacatJavaQueryTransformer queryTransformer =
512
                new EcogridJavaToMetacatJavaQueryTransformer();
513
            QuerySpecification metacatQuery = queryTransformer
514
                    .transform(queryType);
515
516
            DBQuery metacat = new DBQuery();
517
518
            boolean useXMLIndex = (new Boolean(PropertyService
519
                    .getProperty("database.usexmlindex"))).booleanValue();
520
            String xmlquery = "query"; // we don't care the query in resultset,
521
            // the query can be anything
522
            PrintWriter out = null; // we don't want metacat result, so set out null
523
524
            // parameter: queryspecification, user, group, usingIndexOrNot
525
            StringBuffer result = metacat.createResultDocument(xmlquery,
526
                    metacatQuery, out, username, groupNames, useXMLIndex);
527
528
            // create result set transfer
529
            String saxparser = PropertyService.getProperty("xml.saxparser");
530
            MetacatResultsetParser metacatResultsetParser = new MetacatResultsetParser(
531
                    new StringReader(result.toString()), saxparser, queryType
532
                            .getNamespace().get_value());
533
            ResultsetType records = metacatResultsetParser.getEcogridResult();
534
535
            System.out
536
                    .println(EcogridResultsetTransformer.toXMLString(records));
537
            response.setContentType("text/xml");
538
            out = response.getWriter();
539
            out.print(EcogridResultsetTransformer.toXMLString(records));
540
541
        } catch (Exception e) {
542
            e.printStackTrace();
543
        }*/
544
        response.setContentType("text/xml");
545
        PrintWriter out = response.getWriter();
546
        out.print("<error>Query operation not yet supported by Metacat.</error>");
547
        out.close();
548
    }
549 5319 jones
550 5211 jones
    /**
551
     * Earthgrid API > Put Service >Put Function : calls MetacatHandler > handleInsertOrUpdateAction
552
     *
553 5319 jones
     * @param guid ID of data object to be inserted or updated
554 5211 jones
     * @throws IOException
555
     */
556 5319 jones
    private void putObject(String guid, String action) {
557
        logMetacat.debug("Entering putObject: " + guid + "/" + action);
558
559 5286 jones
        // TODO: This function lacks proper handling of authz and authn, so it
560
        // seems that anyone can insert or update; interacts with
561 5319 jones
        // loadSessionData(), which doesn't validate the session
562 5286 jones
563 5319 jones
        // Get an output stream for handling errors; this should really be passed in as
564
        // a parameter
565
        OutputStream out = null;
566
        try {
567
            out = response.getOutputStream();
568
        } catch (IOException e1) {
569
            logMetacat.error("Could not get the output stream for writing in putObject");
570
        }
571
        try {
572
            if (action.equals(FUNCTION_NAME_UPDATE)
573
                    || action.equals(FUNCTION_NAME_INSERT)) {
574 5211 jones
575 5319 jones
                // Check if the objectId exists
576
                IdentifierManager im = IdentifierManager.getInstance();
577
                if (im.identifierExists(guid)) {
578
                    throw new IdentifierNotUnique(1000, "Identifier is already in use: " + guid);
579
                }
580 5211 jones
581 5319 jones
                // TODO: For updates, need to check if the old id exists, and if not throw an exception
582 5211 jones
583 5319 jones
                // TODO: Change this to read the MIME forms that are created
584
                logMetacat.debug("Disassembling MIME multipart form");
585
                InputStream object = null;
586
                InputStream sysmeta = null;
587
                MimeMultipart mmp = new MimeMultipart(new InputStreamDataSource("message", request.getInputStream()));
588
                logMetacat.debug("MMP created.");
589
                mmp.writeTo(System.out);
590
                for (int i = 0; i < mmp.getCount(); i++) {
591
                    logMetacat.debug("Looping over MMP parts: " + i);
592
                    BodyPart part = mmp.getBodyPart(i);
593
                    String name = part.getFileName();
594
                    logMetacat.debug("Part name is: " + name);
595
                    logMetacat.debug("Part has class name: " + part.getClass().getName());
596
                    if (name.equals("object")) {
597
                        object = part.getInputStream();
598
                        logMetacat.debug("Found object part, size is: " + part.getSize());
599
                    } else if (name.equals("systemmetadata")) {
600
                        sysmeta = part.getInputStream();
601
                        logMetacat.debug("Found sysmeta part, size is: " + part.getSize());
602
                    } else {
603
                        throw new InvalidRequest(1000, "Request had malformed MIME part with name: " + name);
604
                    }
605
                }
606
607
                //if (username != null && !username.equals("public")) {
608
                if (username != null) {
609
610
                    logMetacat.debug("Commence creation...");
611
                    AuthToken token = null;
612
                    SystemMetadata m = new SystemMetadata(sysmeta);
613
                    logMetacat.debug(m.serialize(SystemMetadata.FMT_XML));
614
                    //IOUtils.copy(object, System.out);
615
//                    byte[] b = new byte[2048];
616
//                    int len = object.read(b);
617
//                    logMetacat.debug("Read " + len + " bytes from object: " + new String(b));
618
                    CrudService cs = new CrudService(servletContext, request, response);
619
                    cs.create(token, new IdentifierType(guid), object, m);
620
621
                } else {
622
                    logMetacat.debug("Unauthorized to create.");
623
                    throw new NotAuthorized(1000, "Permission denied for user " + username);
624
                }
625 5211 jones
            } else {
626 5319 jones
                throw new InvalidRequest(1000, "Operation must be create or update.");
627 5211 jones
            }
628 5319 jones
        } catch (NotAuthorized e) {
629
            serializeException(e, out);
630
        } catch (InvalidToken e) {
631
            serializeException(e, out);
632
        } catch (ServiceFailure e) {
633
            serializeException(e, out);
634
        } catch (IdentifierNotUnique e) {
635
            serializeException(e, out);
636
        } catch (UnsupportedType e) {
637
            serializeException(e, out);
638
        } catch (InsufficientResources e) {
639
            serializeException(e, out);
640
        } catch (InvalidSystemMetadata e) {
641
            serializeException(e, out);
642
        } catch (NotImplemented e) {
643
            serializeException(e, out);
644
        } catch (InvalidRequest e) {
645
            serializeException(e, out);
646
        } catch (MessagingException e) {
647
            ServiceFailure sf = new ServiceFailure(1000, e.getMessage());
648
            serializeException(sf, out);
649
        } catch (IOException e) {
650
            ServiceFailure sf = new ServiceFailure(1000, e.getMessage());
651
            serializeException(sf, out);
652 5211 jones
        }
653
    }
654
655
    /**
656
     * Earthgrid API > Put Service > Delete Function : calls MetacatHandler > handleDeleteAction
657
     *
658 5287 jones
     * @param guid ID of data object to be deleted
659 5211 jones
     * @throws IOException
660
     */
661 5287 jones
    private void deleteObject(String guid) throws IOException
662
    {
663
        // Look up the localId for this global identifier
664
        IdentifierManager im = IdentifierManager.getInstance();
665
        String localId = "";
666
        try {
667
            localId = im.getLocalId(guid);
668
        } catch (McdbDocNotFoundException e) {
669
            // TODO: Need to return the proper DataONE exception
670
        }
671
672
        params.put("docid", new String[] { localId });
673 5211 jones
        PrintWriter out = response.getWriter();
674
        handler.handleDeleteAction(out, params, request, response, username,
675
                groupNames);
676
        out.close();
677
    }
678
679
    /**
680
     * Earthgrid API > Authentication Service > Login Function : calls MetacatHandler > handleLoginAction
681
     *
682
     * @throws IOException
683
     */
684
    private void login() throws IOException {
685
        PrintWriter out = response.getWriter();
686
        handler.handleLoginAction(out, params, request, response);
687
        out.close();
688
    }
689
690
    /**
691
     * Earthgrid API > Authentication Service > Logout Function : calls MetacatHandler > handleLogoutAction
692
     *
693
     * @throws IOException
694
     */
695
    private void logout() throws IOException {
696
        PrintWriter out = response.getWriter();
697
        handler.handleLogoutAction(out, params, request, response);
698
        out.close();
699
    }
700
701
    /**
702
     * Prints xml response
703
     * @param message Message to be displayed
704
     * @param response Servlet response that xml message will be printed
705
     * */
706
    private void printError(String message, HttpServletResponse response) {
707
        try {
708
            PrintWriter out = response.getWriter();
709
            response.setContentType("text/xml");
710
            out.println("<?xml version=\"1.0\"?>");
711
            out.println("<error>");
712
            out.println(message);
713
            out.println("</error>");
714
            out.close();
715
        } catch (IOException e) {
716
            e.printStackTrace();
717
        }
718
    }
719
720 5319 jones
    private void serializeException(BaseException e, OutputStream out) {
721
        // TODO: Use content negotiation to determine which return format to use
722
        response.setContentType("text/xml");
723
        response.setStatus(e.getCode());
724
        try {
725
            IOUtils.write(e.serialize(BaseException.FMT_XML), out);
726
        } catch (IOException e1) {
727
            logMetacat.error("Error writing exception to stream. "
728
                    + e1.getMessage());
729
        }
730
    }
731
732 5211 jones
}