Project

General

Profile

1 5298 jones
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6 5299 jones
 *   '$Author: $'
7 5298 jones
 *     '$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.dataone;
24
25 5329 jones
import java.io.ByteArrayOutputStream;
26 5319 jones
import java.io.File;
27 5679 berkley
import java.io.FileInputStream;
28 5319 jones
import java.io.FileNotFoundException;
29
import java.io.FileOutputStream;
30 5298 jones
import java.io.IOException;
31
import java.io.InputStream;
32
import java.io.OutputStream;
33 5953 cjones
34 5920 jones
import java.security.NoSuchAlgorithmException;
35 5953 cjones
36 5298 jones
import java.sql.SQLException;
37 5953 cjones
38 5364 berkley
import java.text.DateFormat;
39 5953 cjones
40 5920 jones
import java.util.Calendar;
41
import java.util.Date;
42
import java.util.Enumeration;
43
import java.util.Hashtable;
44
import java.util.List;
45
import java.util.TimeZone;
46
import java.util.Timer;
47
import java.util.TimerTask;
48
import java.util.Vector;
49 5298 jones
50
import javax.servlet.http.HttpServletRequest;
51
52 5953 cjones
import javax.xml.parsers.ParserConfigurationException;
53
import javax.xml.xpath.XPathExpressionException;
54
55 5319 jones
import org.apache.commons.io.IOUtils;
56
import org.apache.log4j.Logger;
57 5953 cjones
58
import org.dataone.eml.DataoneEMLParser;
59
import org.dataone.eml.EMLDocument;
60
import org.dataone.eml.EMLDocument.DistributionMetadata;
61
62 5920 jones
import org.dataone.service.exceptions.BaseException;
63 5298 jones
import org.dataone.service.exceptions.IdentifierNotUnique;
64
import org.dataone.service.exceptions.InsufficientResources;
65
import org.dataone.service.exceptions.InvalidRequest;
66
import org.dataone.service.exceptions.InvalidSystemMetadata;
67
import org.dataone.service.exceptions.InvalidToken;
68
import org.dataone.service.exceptions.NotAuthorized;
69
import org.dataone.service.exceptions.NotFound;
70
import org.dataone.service.exceptions.NotImplemented;
71
import org.dataone.service.exceptions.ServiceFailure;
72
import org.dataone.service.exceptions.UnsupportedType;
73 5953 cjones
74 5298 jones
import org.dataone.service.mn.MemberNodeCrud;
75 5953 cjones
76 5920 jones
import org.dataone.service.types.AuthToken;
77
import org.dataone.service.types.Checksum;
78
import org.dataone.service.types.ChecksumAlgorithm;
79
import org.dataone.service.types.DescribeResponse;
80
import org.dataone.service.types.Event;
81
import org.dataone.service.types.Identifier;
82
import org.dataone.service.types.Log;
83
import org.dataone.service.types.LogEntry;
84
import org.dataone.service.types.NodeReference;
85
import org.dataone.service.types.ObjectFormat;
86
import org.dataone.service.types.ObjectList;
87
import org.dataone.service.types.Principal;
88
import org.dataone.service.types.SystemMetadata;
89
import org.dataone.service.types.util.ServiceTypeUtil;
90 5953 cjones
91 5329 jones
import org.jibx.runtime.BindingDirectory;
92
import org.jibx.runtime.IBindingFactory;
93
import org.jibx.runtime.IMarshallingContext;
94 5332 jones
import org.jibx.runtime.IUnmarshallingContext;
95 5329 jones
import org.jibx.runtime.JiBXException;
96 5298 jones
97 5953 cjones
import org.xml.sax.SAXException;
98
99 5798 berkley
import edu.ucsb.nceas.metacat.AccessionNumber;
100 5319 jones
import edu.ucsb.nceas.metacat.AccessionNumberException;
101
import edu.ucsb.nceas.metacat.DocumentImpl;
102
import edu.ucsb.nceas.metacat.EventLog;
103 5298 jones
import edu.ucsb.nceas.metacat.IdentifierManager;
104
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
105
import edu.ucsb.nceas.metacat.McdbException;
106
import edu.ucsb.nceas.metacat.MetacatHandler;
107
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
108 5370 berkley
import edu.ucsb.nceas.metacat.client.rest.MetacatRestClient;
109 5319 jones
import edu.ucsb.nceas.metacat.properties.PropertyService;
110
import edu.ucsb.nceas.metacat.replication.ForceReplicationHandler;
111 5298 jones
import edu.ucsb.nceas.metacat.service.SessionService;
112 6088 cjones
import edu.ucsb.nceas.metacat.service.ObjectFormatService;
113 5329 jones
import edu.ucsb.nceas.metacat.util.DocumentUtil;
114 5298 jones
import edu.ucsb.nceas.metacat.util.SessionData;
115 5953 cjones
116 5298 jones
import edu.ucsb.nceas.utilities.ParseLSIDException;
117
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
118
119
/**
120
 *
121
 * Implements DataONE MemberNode CRUD API for Metacat.
122
 *
123
 * @author Matthew Jones
124
 */
125 5394 berkley
public class CrudService implements MemberNodeCrud
126
{
127 5337 berkley
    private static CrudService crudService = null;
128 5298 jones
129
    private MetacatHandler handler;
130
    private Hashtable<String, String[]> params;
131 5392 berkley
    private Logger logMetacat = null;
132
    private Logger logCrud = null;
133 5337 berkley
134
    private String metacatUrl;
135 5420 berkley
136 5298 jones
    /**
137 5337 berkley
     * singleton accessor
138
     */
139 5630 berkley
    public static CrudService getInstance()
140 5337 berkley
    {
141
      if(crudService == null)
142
      {
143
        crudService = new CrudService();
144
      }
145
146
      return crudService;
147
    }
148
149
    /**
150 5770 berkley
     * Constructor, private for singleton access
151 5298 jones
     */
152 5763 berkley
    private CrudService() {
153 5337 berkley
        logMetacat = Logger.getLogger(CrudService.class);
154 5392 berkley
        logCrud = Logger.getLogger("DataOneLogger");
155 5337 berkley
        try
156
        {
157
            String server = PropertyService.getProperty("server.name");
158
            String port = PropertyService.getProperty("server.httpPort");
159
            String context = PropertyService.getProperty("application.context");
160 5746 berkley
            metacatUrl = "http://" + server + ":" + port + "/" + context + "/d1";
161 5337 berkley
            logMetacat.debug("Initializing CrudService with url " + metacatUrl);
162
        }
163
        catch(Exception e)
164
        {
165
            logMetacat.error("Could not find servlet url in CrudService: " + e.getMessage());
166
            e.printStackTrace();
167
            throw new RuntimeException("Error getting servlet url in CrudService: " + e.getMessage());
168
        }
169
170
        params = new Hashtable<String, String[]>();
171
        handler = new MetacatHandler(new Timer());
172 5298 jones
    }
173 5337 berkley
174 5298 jones
    /**
175 5337 berkley
     * return the context url CrudService is using.
176 5298 jones
     */
177 5337 berkley
    public String getContextUrl()
178
    {
179
        return metacatUrl;
180
    }
181
182
    /**
183 5394 berkley
     * Set the context url that this service uses.  It is normally not necessary
184
     * to call this method unless you are trying to connect to a server other
185
     * than the one in which this service is installed.  Otherwise, this value is
186
     * taken from the metacat.properties file (server.name, server.port, application.context).
187
     */
188
    public void setContextUrl(String url)
189
    {
190
        metacatUrl = url;
191
    }
192
193
    /**
194 5337 berkley
     * set the params for this service from an HttpServletRequest param list
195
     */
196
    public void setParamsFromRequest(HttpServletRequest request)
197
    {
198 5921 jones
        @SuppressWarnings("unchecked")
199
        Enumeration<String> paramlist = request.getParameterNames();
200 5298 jones
        while (paramlist.hasMoreElements()) {
201 5337 berkley
            String name = (String) paramlist.nextElement();
202
            String[] value = (String[])request.getParameterValues(name);
203 5298 jones
            params.put(name, value);
204
        }
205
    }
206
207 5337 berkley
    /**
208 5370 berkley
     * Authenticate against metacat and get a token.
209
     * @param username
210
     * @param password
211
     * @return
212
     * @throws ServiceFailure
213
     */
214
    public AuthToken authenticate(String username, String password)
215
      throws ServiceFailure
216
    {
217 5466 berkley
        /* TODO:
218
         * This method is not in the original D1 crud spec.  It is highly
219
         * metacat centric.  Higher level decisions need to be made on authentication
220
         * interfaces for D1 nodes.
221
         */
222 5370 berkley
        try
223
        {
224
            MetacatRestClient restClient = new MetacatRestClient(getContextUrl());
225
            String response = restClient.login(username, password);
226
            String sessionid = restClient.getSessionId();
227
            SessionService sessionService = SessionService.getInstance();
228
            sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
229
            AuthToken token = new AuthToken(sessionid);
230 5383 berkley
            EventLog.getInstance().log(metacatUrl,
231 5384 berkley
                    username, null, "authenticate");
232 5436 berkley
            logCrud.info("authenticate");
233 5370 berkley
            return token;
234
        }
235
        catch(Exception e)
236
        {
237 5624 berkley
            throw new ServiceFailure("1620", "Error authenticating with metacat: " + e.getMessage());
238 5370 berkley
        }
239
    }
240
241
    /**
242 5337 berkley
     * set the parameter values needed for this request
243
     */
244
    public void setParameter(String name, String[] value)
245
    {
246
        params.put(name, value);
247
    }
248
249 5377 berkley
    /**
250
     * Generate SystemMetadata for any object in the object store that does
251
     * not already have it.  SystemMetadata documents themselves, are, of course,
252
     * exempt.  This is a utility method for migration of existing object
253
     * stores to DataONE where SystemMetadata is required for all objects.  See
254
     * https://trac.dataone.org/ticket/591
255 5378 berkley
     *
256
     * @param token an authtoken with appropriate permissions to read all
257
     * documents in the object store.  To work correctly, this should probably
258
     * be an adminstrative credential.
259 6068 rnahf
     * @throws SQLException
260
     * @throws AccessionNumberException
261
     * @throws NoSuchAlgorithmException
262
     * @throws InvalidRequest
263
     * @throws NotImplemented
264
     * @throws NotFound
265
     * @throws NotAuthorized
266
     * @throws InvalidToken
267
     * @throws PropertyNotFoundException
268
     * @throws McdbDocNotFoundException
269
     * @throws ServiceFailure
270 5377 berkley
     */
271 6068 rnahf
    public void generateMissingSystemMetadata(AuthToken token)
272
    throws ServiceFailure, McdbDocNotFoundException, PropertyNotFoundException, InvalidToken, NotAuthorized,
273
    NotFound, NotImplemented, InvalidRequest, NoSuchAlgorithmException, AccessionNumberException, SQLException
274
    {
275 5378 berkley
        IdentifierManager im = IdentifierManager.getInstance();
276 5377 berkley
        //get the list of ids with no SM
277 5920 jones
        List<String> idList = im.getLocalIdsWithNoSystemMetadata();
278
        for (String localId : idList) {
279
            //for each id, add a system metadata doc
280
            generateMissingSystemMetadata(token, localId);
281
        }
282
        logCrud.info("generateMissingSystemMetadata(token)");
283
    }
284
285
    /**
286
     * Generate SystemMetadata for a particular object with identifier localId.
287
     * This is a utility method for migration of existing objects
288
     * to DataONE where SystemMetadata is required for all objects.
289
     *
290
     * @param token an authtoken with appropriate permissions to read all
291
     *        documents in the object store.  To work correctly, this should
292
     *        be an adminstrative credential.
293
     * @param localId the identifier of the object to be processed
294 6068 rnahf
     * @throws ServiceFailure
295
     * @throws SQLException
296
     * @throws AccessionNumberException
297
     * @throws NoSuchAlgorithmException
298
     * @throws InvalidRequest
299
     * @throws NotImplemented
300
     * @throws NotFound
301
     * @throws NotAuthorized
302
     * @throws InvalidToken
303
     * @throws PropertyNotFoundException
304
     * @throws McdbDocNotFoundException
305 5920 jones
     */
306 6068 rnahf
    public void generateMissingSystemMetadata(AuthToken token, String localId)
307
    throws ServiceFailure, McdbDocNotFoundException, PropertyNotFoundException, InvalidToken, NotAuthorized,
308
    NotFound, NotImplemented, InvalidRequest, NoSuchAlgorithmException, AccessionNumberException, SQLException
309
    {
310
    	logCrud.debug("CrudService.generateMissingSystemMetadata() called.");
311 5953 cjones
        logCrud.debug("Creating SystemMetadata for localId " + localId);
312 6068 rnahf
        SystemMetadata sm = null;
313
314
        //generate required system metadata fields from the document
315 5920 jones
        try {
316 6068 rnahf
        	sm = createSystemMetadata(localId, token);
317
        } catch (IOException e1) {
318
        	e1.printStackTrace();
319
        	ServiceFailure sf = new ServiceFailure("00","IOException in generateMissingSystemMetadata: " +
320
        			e1.getMessage());
321
        	sf.setStackTrace(e1.getStackTrace());
322
        	throw sf;
323
        }
324
325
        //insert the systemmetadata object
326
        SessionData sessionData = getSessionData(token);
327
        String smlocalid = insertSystemMetadata(sm, sessionData);
328
        logCrud.debug("setting access on SM doc with localid " + smlocalid);
329
        try {
330
        	handler.setAccess(metacatUrl, sessionData.getUserName(), smlocalid, "public", "4", "allow", "allowFirst");
331
        } catch (Exception e) {
332
        	logCrud.debug("Unspecified exception thrown by MetacatHandler.setAccess(): " + e.getMessage());
333
        	logMetacat.error("Could not generate missing systemMetadata: " + e.getMessage());
334
        	logMetacat.error(e.getStackTrace());
335
        	ServiceFailure sf = new ServiceFailure("0","Unspecified exception thrown by MetacatHandler.setAccess(): " + e.getMessage());
336
        	sf.setStackTrace(e.getStackTrace());
337
        	throw sf;
338
        }
339 5920 jones
340 6068 rnahf
        String username = "public";
341
        if (sessionData != null) {
342
        	username = sessionData.getUserName();
343 5377 berkley
        }
344 6068 rnahf
        EventLog.getInstance().log(metacatUrl, username, localId, "generateMissingSystemMetadata");
345
346
//        catch (Exception e) { // TODO: Please don't catch Exception -- it masks bad things
347
//            e.printStackTrace();
348
//            logCrud.debug("Exception generating missing system metadata: " + e.getMessage());
349
//            logMetacat.error("Could not generate missing system metadata: " + e.getMessage());
350
//        }
351 5920 jones
        logCrud.info("generateMissingSystemMetadata(token, localId)");
352 5377 berkley
    }
353
354 5378 berkley
    /**
355 5379 berkley
     * create an object via the crud interface
356 5378 berkley
     */
357 5320 jones
    public Identifier create(AuthToken token, Identifier guid,
358 5298 jones
            InputStream object, SystemMetadata sysmeta) throws InvalidToken,
359
            ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType,
360
            InsufficientResources, InvalidSystemMetadata, NotImplemented {
361 5319 jones
        logMetacat.debug("Starting CrudService.create()...");
362
363 5329 jones
        // authenticate & get user info
364
        SessionData sessionData = getSessionData(token);
365 5431 berkley
        String username = "public";
366
        String[] groups = null;
367
        if(sessionData != null)
368
        {
369
            username = sessionData.getUserName();
370
            groups = sessionData.getGroupNames();
371
        }
372 5383 berkley
        String localId = null;
373 5319 jones
374 5376 berkley
        if (username == null || username.equals("public"))
375
        {
376 5466 berkley
            //TODO: many of the thrown exceptions do not use the correct error codes
377
            //check these against the docs and correct them
378 5624 berkley
            throw new NotAuthorized("1100", "User " + username + " is not authorized to create content." +
379 5376 berkley
                    "  If you are not logged in, please do so and retry the request.");
380
        }
381
382 5319 jones
        // verify that guid == SystemMetadata.getIdentifier()
383 5320 jones
        logMetacat.debug("Comparing guid|sysmeta_guid: " + guid.getValue() + "|" + sysmeta.getIdentifier().getValue());
384 5329 jones
        if (!guid.getValue().equals(sysmeta.getIdentifier().getValue())) {
385 5356 berkley
            throw new InvalidSystemMetadata("1180",
386 5750 berkley
                "GUID in method call (" + guid.getValue() + ") does not match GUID in system metadata (" +
387
                sysmeta.getIdentifier().getValue() + ").");
388 5329 jones
        }
389 5319 jones
390
        logMetacat.debug("Checking if identifier exists...");
391
        // Check that the identifier does not already exist
392 5436 berkley
        IdentifierManager im = IdentifierManager.getInstance();
393 5320 jones
        if (im.identifierExists(guid.getValue())) {
394 5356 berkley
            throw new IdentifierNotUnique("1120",
395 5319 jones
                "GUID is already in use by an existing object.");
396
        }
397
398 5329 jones
        // Check if we are handling metadata or data
399
        boolean isScienceMetadata = isScienceMetadata(sysmeta);
400 5319 jones
401 5329 jones
        if (isScienceMetadata) {
402 5331 jones
            // CASE METADATA:
403
            try {
404 5953 cjones
                //logCrud.debug("CrudService: inserting document with guid " + guid.getValue());
405 5350 berkley
                this.insertDocument(object, guid, sessionData);
406 5383 berkley
                localId = im.getLocalId(guid.getValue());
407 5331 jones
            } catch (IOException e) {
408
                String msg = "Could not create string from XML stream: " +
409
                    " " + e.getMessage();
410
                logMetacat.debug(msg);
411 5356 berkley
                throw new ServiceFailure("1190", msg);
412 5383 berkley
            } catch(Exception e) {
413
                String msg = "Unexpected error in CrudService.create: " + e.getMessage();
414
                logMetacat.debug(msg);
415
                throw new ServiceFailure("1190", msg);
416 5331 jones
            }
417 5383 berkley
418 5319 jones
419 5329 jones
        } else {
420 5331 jones
            // DEFAULT CASE: DATA (needs to be checked and completed)
421 5460 berkley
            localId = insertDataObject(object, guid, sessionData);
422 5331 jones
423
        }
424 5319 jones
425 5331 jones
        // For Metadata and Data, insert the system metadata into the object store too
426 5441 berkley
        String sysMetaLocalId = insertSystemMetadata(sysmeta, sessionData);
427
        //get the document info.  add any access params for the sysmeta too
428 5953 cjones
        //logCrud.debug("looking for access records to add for system " +
429 5466 berkley
        //    "metadata who's parent doc's  local id is " + localId);
430 5441 berkley
        try
431
        {
432 5444 berkley
            Hashtable<String, Object> h = im.getDocumentInfo(localId.substring(0, localId.lastIndexOf(".")));
433 5441 berkley
            Vector v = (Vector)h.get("access");
434
            for(int i=0; i<v.size(); i++)
435
            {
436 5921 jones
                @SuppressWarnings("unchecked")
437
                Hashtable<String, String> ah = (Hashtable<String, String>)v.elementAt(i);
438 5441 berkley
                String principal = (String)ah.get("principal_name");
439
                String permission = (String)ah.get("permission");
440
                String permissionType = (String)ah.get("permission_type");
441
                String permissionOrder = (String)ah.get("permission_order");
442 5443 berkley
                int perm = new Integer(permission).intValue();
443 5953 cjones
                //logCrud.debug("found access record for principal " + principal);
444
                //logCrud.debug("permission: " + perm + " perm_type: " + permissionType +
445 5466 berkley
                //    " perm_order: " + permissionOrder);
446 5444 berkley
                this.setAccess(token, guid, principal, perm, permissionType, permissionOrder, true);
447 5441 berkley
            }
448
        }
449
        catch(Exception e)
450
        {
451
            logMetacat.error("Error setting permissions on System Metadata object " +
452
                    " with id " + sysMetaLocalId + ": " + e.getMessage());
453 5466 berkley
            //TODO: decide if this error should cancel the entire create or
454
            //if it should continue with just a logged error.
455 5441 berkley
        }
456
457
458 5319 jones
        logMetacat.debug("Returning from CrudService.create()");
459 5383 berkley
        EventLog.getInstance().log(metacatUrl,
460 5384 berkley
                username, localId, "create");
461 5459 berkley
        logCrud.info("create D1GUID:" + guid.getValue() + ":D1SCIMETADATA:" + localId +
462 5582 berkley
                ":D1SYSMETADATA:"+ sysMetaLocalId + ":");
463 5319 jones
        return guid;
464 5298 jones
    }
465 5353 berkley
466
    /**
467
     * update an existing object with a new object.  Change the system metadata
468
     * to reflect the changes and update it as well.
469
     */
470
    public Identifier update(AuthToken token, Identifier guid,
471
            InputStream object, Identifier obsoletedGuid, SystemMetadata sysmeta)
472
            throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique,
473
            UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata,
474
            NotImplemented {
475 6068 rnahf
    	try
476
    	{
477
    		SessionData sessionData = getSessionData(token);
478 5353 berkley
479
            //find the old systemmetadata (sm.old) document id (the one linked to obsoletedGuid)
480
            SystemMetadata sm = getSystemMetadata(token, obsoletedGuid);
481
            //change sm.old's obsoletedBy field
482 5921 jones
            List<Identifier> l = sm.getObsoletedByList();
483 5353 berkley
            l.add(guid);
484
            sm.setObsoletedByList(l);
485
            //update sm.old
486
            updateSystemMetadata(sm, sessionData);
487
488
            //change the obsoletes field of the new systemMetadata (sm.new) to point to the id of the old one
489
            sysmeta.addObsolete(obsoletedGuid);
490
            //insert sm.new
491 5459 berkley
            String sysMetaLocalId = insertSystemMetadata(sysmeta, sessionData);
492
            String localId;
493 5353 berkley
494
            boolean isScienceMetadata = isScienceMetadata(sysmeta);
495
            if(isScienceMetadata)
496
            {
497
                //update the doc
498 5459 berkley
                localId = updateDocument(object, obsoletedGuid, guid, sessionData, false);
499 5353 berkley
            }
500
            else
501
            {
502
                //update a data file, not xml
503 5459 berkley
                localId = insertDataObject(object, guid, sessionData);
504 5353 berkley
            }
505 5383 berkley
506
            IdentifierManager im = IdentifierManager.getInstance();
507 5431 berkley
            String username = "public";
508
            if(sessionData != null)
509
            {
510
                username = sessionData.getUserName();
511
            }
512 5383 berkley
            EventLog.getInstance().log(metacatUrl,
513 5384 berkley
                    username, im.getLocalId(guid.getValue()), "update");
514 5459 berkley
            logCrud.info("update D1GUID:" + guid.getValue() + ":D1SCIMETADATA:" + localId +
515 5582 berkley
                    ":D1SYSMETADATA:"+ sysMetaLocalId + ":");
516 5353 berkley
            return guid;
517
        }
518 6068 rnahf
519
    	catch(IOException e) {
520 5624 berkley
            throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
521 5353 berkley
        }
522 6068 rnahf
    	catch( McdbDocNotFoundException e) {
523
    		throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
524
    	}
525
    	catch( InvalidRequest e) {
526
    		throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
527
    	}
528 5353 berkley
    }
529 5359 berkley
530
    /**
531 5521 berkley
     * set access permissions on both the science metadata and system metadata
532
     */
533
    public void setAccess(AuthToken token, Identifier id, String principal, String permission,
534
            String permissionType, String permissionOrder)
535
      throws ServiceFailure
536
    {
537
        setAccess(token, id, principal, permission, permissionType, permissionOrder, true);
538
    }
539
540
    /**
541 5443 berkley
     * set access control on the doc
542
     * @param token
543
     * @param id
544
     * @param principal
545
     * @param permission
546
     */
547
    public void setAccess(AuthToken token, Identifier id, String principal, int permission,
548
      String permissionType, String permissionOrder, boolean setSystemMetadata)
549
      throws ServiceFailure
550
    {
551
        String perm = "";
552 5445 berkley
        if(permission >= 4)
553 5443 berkley
        {
554
            perm = "read";
555
        }
556 5445 berkley
        if(permission >= 6)
557 5443 berkley
        {
558
            perm = "write";
559
        }
560 5953 cjones
        //logCrud.debug("perm in setAccess: " + perm);
561
        //logCrud.debug("permission in setAccess: " + permission);
562 5443 berkley
        setAccess(token, id, principal, perm, permissionType, permissionOrder,
563
                setSystemMetadata);
564
565
    }
566
567
    /**
568 5362 berkley
     * set the permission on the document
569
     * @param token
570
     * @param principal
571
     * @param permission
572
     * @param permissionType
573
     * @param permissionOrder
574
     * @return
575
     */
576
    public void setAccess(AuthToken token, Identifier id, String principal, String permission,
577 5424 berkley
            String permissionType, String permissionOrder, boolean setSystemMetadata)
578 5362 berkley
      throws ServiceFailure
579
    {
580 5466 berkley
        /* TODO:
581
         * This is also not part of the D1 Crud spec.  This method is needed for
582
         * systems such as metacat where access to objects is controlled by
583
         * and ACL.  Higher level decisions need to be made about how this
584
         * should work within D1.
585
         */
586 5362 berkley
        try
587
        {
588 5449 berkley
            final SessionData sessionData = getSessionData(token);
589
            if(sessionData == null)
590
            {
591
                throw new ServiceFailure("1000", "User must be logged in to set access.");
592
            }
593 5362 berkley
            IdentifierManager im = IdentifierManager.getInstance();
594
            String docid = im.getLocalId(id.getValue());
595 5449 berkley
596 5362 berkley
            String permNum = "0";
597 5370 berkley
            if(permission.equals("read"))
598 5362 berkley
            {
599
                permNum = "4";
600
            }
601 5370 berkley
            else if(permission.equals("write"))
602 5362 berkley
            {
603
                permNum = "6";
604
            }
605 5953 cjones
            logCrud.debug("user " + sessionData.getUserName() +
606 5424 berkley
                    " is setting access level " + permNum + " for permission " +
607
                    permissionType + " on doc with localid " + docid);
608 5362 berkley
            handler.setAccess(metacatUrl, sessionData.getUserName(), docid,
609
                    principal, permNum, permissionType, permissionOrder);
610 5424 berkley
            if(setSystemMetadata)
611
            {
612
                //set the same perms on the system metadata doc
613
                String smlocalid = im.getSystemMetadataLocalId(id.getValue());
614 5953 cjones
                logCrud.debug("setting access on SM doc with localid " + smlocalid);
615 5424 berkley
                //cs.setAccess(token, smid, principal, permission, permissionType, permissionOrder);
616
                handler.setAccess(metacatUrl, sessionData.getUserName(), smlocalid,
617
                        principal, permNum, permissionType, permissionOrder);
618
            }
619 5431 berkley
            String username = "public";
620
            if(sessionData != null)
621
            {
622
                username = sessionData.getUserName();
623
            }
624 5383 berkley
            EventLog.getInstance().log(metacatUrl,
625 5384 berkley
                    username, im.getLocalId(id.getValue()), "setAccess");
626 5392 berkley
            logCrud.info("setAccess");
627 5362 berkley
        }
628
        catch(Exception e)
629
        {
630 5370 berkley
            e.printStackTrace();
631 5362 berkley
            throw new ServiceFailure("1000", "Could not set access on the document with id " + id.getValue());
632
        }
633
    }
634
635
    /**
636 5359 berkley
     *  Retrieve the list of objects present on the MN that match the calling
637
     *  parameters. This method is required to support the process of Member
638
     *  Node synchronization. At a minimum, this method should be able to
639
     *  return a list of objects that match:
640
     *  startTime <= SystemMetadata.dateSysMetadataModified
641
     *  but is expected to also support date range (by also specifying endTime),
642
     *  and should also support slicing of the matching set of records by
643
     *  indicating the starting index of the response (where 0 is the index
644
     *  of the first item) and the count of elements to be returned.
645
     *
646 5364 berkley
     *  If startTime or endTime is null, the query is not restricted by that parameter.
647
     *
648 5359 berkley
     * @see http://mule1.dataone.org/ArchitectureDocs/mn_api_replication.html#MN_replication.listObjects
649
     * @param token
650
     * @param startTime
651
     * @param endTime
652
     * @param objectFormat
653
     * @param replicaStatus
654
     * @param start
655
     * @param count
656
     * @return ObjectList
657
     * @throws NotAuthorized
658
     * @throws InvalidRequest
659
     * @throws NotImplemented
660
     * @throws ServiceFailure
661
     * @throws InvalidToken
662
     */
663
    public ObjectList listObjects(AuthToken token, Date startTime, Date endTime,
664
        ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
665
      throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
666
    {
667 5895 berkley
      //ObjectList ol = new ObjectList();
668
      //final SessionData sessionData = getSessionData(token);
669
      //int totalAfterQuery = 0;
670 5510 berkley
671
672 5895 berkley
      return IdentifierManager.getInstance().querySystemMetadata(startTime, endTime,
673
              objectFormat, replicaStatus, start, count);
674
675
676
      /////////////////////////////////////////////////////////////////////////
677
      ///////////////// OLD CODE //////////////////////////////////////////////
678
      /////////////////////////////////////////////////////////////////////////
679
680
//      try
681
//      {
682
//          if (PropertyService.getProperty("database.queryCacheOn").equals("true"))
683
//          {
684
//              //System.out.println("the string stored into cache is "+ resultsetBuffer.toString());
685
//              DBQuery.clearQueryResultCache();
686
//          }
687
//      }
688
//      catch (PropertyNotFoundException e1)
689
//      {
690
//          //just don't do anything
691
//      }
692
//
693
//      try
694
//      {
695
//          //TODO: Milliseconds need to be added to the dateFormat
696
//          System.out.println("=========== Listing Objects =============");
697
//          System.out.println("Current server time is: " + new Date());
698
//          if(startTime != null)
699
//          {
700
//              System.out.println("query start time is " + startTime);
701
//          }
702
//          if(endTime != null)
703
//          {
704
//              System.out.println("query end time is " + endTime);
705
//          }
706
//          params.clear();
707
//          params.put("qformat", new String[] {PropertyService.getProperty("crudService.listObjects.QFormat")});
708
//          params.put("action", new String[] {"squery"});
709
//          params.put("query", new String[] {createListObjectsPathQueryDocument()});
710
//
711
//          /*System.out.println("query is: metacatUrl: " + metacatUrl + " user: " + sessionData.getUserName() +
712
//                  " sessionid: " + sessionData.getId() + " params: ");
713
//          String url = metacatUrl + "/metacat?action=query&sessionid=" + sessionData.getId();
714
//          Enumeration keys = params.keys();
715
//          while(keys.hasMoreElements())
716
//          {
717
//              String key = (String)keys.nextElement();
718
//              String[] parr = params.get(key);
719
//              for(int i=0; i<parr.length; i++)
720
//              {
721
//                  System.out.println("param " + key + ": " + parr[i]);
722
//                  url += "&" + key + "=" + parr[i] ;
723
//              }
724
//          }
725
//          System.out.println("query url: " + url);
726
//          */
727
//          String username = "public";
728
//          String[] groups = null;
729
//          String sessionid = "";
730
//          if(sessionData != null)
731
//          {
732
//              username = sessionData.getUserName();
733
//              groups = sessionData.getGroupNames();
734
//              sessionid = sessionData.getId();
735
//          }
736
//
737
//          MetacatResultSet rs = handler.query(metacatUrl, params, username,
738
//                  groups, sessionid);
739
//          List docs = rs.getDocuments();
740
//
741
//          System.out.println("query returned " + docs.size() + " documents.");
742
//          Vector<Document> docCopy = new Vector<Document>();
743
//
744
//          //preparse the list to remove any that don't match the query params
745
//          /* TODO: this type of query/subquery processing is probably not scalable
746
//           * to larger object stores.  This code should be revisited.  The metacat
747
//           * query handler should probably be altered to handle the type of query
748
//           * done here.
749
//           */
750
//          for(int i=0; i<docs.size(); i++)
751
//          {
752
//              Document d = (Document)docs.get(i);
753
//
754
//              ObjectFormat returnedObjectFormat = ObjectFormat.convert(d.getField("objectFormat"));
755
//
756
//              if(returnedObjectFormat != null &&
757
//                 objectFormat != null &&
758
//                 !objectFormat.toString().trim().equals(returnedObjectFormat.toString().trim()))
759
//              { //make sure the objectFormat is the one specified
760
//                  continue;
761
//              }
762
//
763
//              String dateSMM = d.getField("dateSysMetadataModified");
764
//              if((startTime != null || endTime != null) && dateSMM == null)
765
//              {  //if startTime or endTime are not null, we need a date to compare to
766
//                  continue;
767
//              }
768
//
769
//              //date parse
770
//              Date dateSysMetadataModified = null;
771
//              if(dateSMM != null)
772
//              {
773
//
774
//                  /*
775
//                  if(dateSMM.indexOf(".") != -1)
776
//                  {  //strip the milliseconds
777
//                      //TODO: don't do this. we need milliseconds now.
778
//                      //TODO: explore ISO 8601 to figure out milliseconds
779
//                      dateSMM = dateSMM.substring(0, dateSMM.indexOf(".")) + 'Z';
780
//                  }
781
//                  */
782
//                  //System.out.println("dateSMM: " + dateSMM);
783
//                  //dateFormat.setTimeZone(TimeZone.getTimeZone("GMT-0"));
784
//                  try
785
//                  {   //the format we want
786
//                      dateSysMetadataModified = dateFormat.parse(dateSMM);
787
//                  }
788
//                  catch(java.text.ParseException pe)
789
//                  {   //try another legacy format
790
//                      try
791
//                      {
792
//                          DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.S'Z'");
793
//                          dateFormat2.setTimeZone(TimeZone.getTimeZone("GMT-0"));
794
//                          dateSysMetadataModified = dateFormat2.parse(dateSMM);
795
//                      }
796
//                      catch(java.text.ParseException pe2)
797
//                      {
798
//                          //try another legacy format
799
//                          DateFormat dateFormat3 = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss'Z'");
800
//                          dateFormat3.setTimeZone(TimeZone.getTimeZone("GMT-0"));
801
//                          dateSysMetadataModified = dateFormat3.parse(dateSMM);
802
//                      }
803
//
804
//                  }
805
//              }
806
//
807
//              /*System.out.println("====================================");
808
//              System.out.println("doc number " + i);
809
//              System.out.println("docid: " + d.docid);
810
//              System.out.println("guid: " + d.getField("identifier").trim());
811
//              System.out.println("dateSMM: " + dateSMM);
812
//              System.out.println("dateSysMetadataModified: " + dateSysMetadataModified);
813
//              System.out.println("startTime: " + startTime);
814
//              System.out.println("endtime: " + endTime);*/
815
//
816
//              int startDateComparison = 0;
817
//              int endDateComparison = 0;
818
//              if(startTime != null)
819
//              {
820
//                  Calendar zTime = Calendar.getInstance(TimeZone.getTimeZone("GMT-0"));
821
//                  zTime.setTime(startTime);
822
//                  startTime = zTime.getTime();
823
//
824
//                  if(dateSysMetadataModified == null)
825
//                  {
826
//                      startDateComparison = -1;
827
//                  }
828
//                  else
829
//                  {
830
//                      startDateComparison = dateSysMetadataModified.compareTo(startTime);
831
//                  }
832
//                  //System.out.println("startDateCom: " + startDateComparison);
833
//              }
834
//              else
835
//              {
836
//                  startDateComparison = 1;
837
//              }
838
//
839
//              if(endTime != null)
840
//              {
841
//                  Calendar zTime = Calendar.getInstance(TimeZone.getTimeZone("GMT-0"));
842
//                  zTime.setTime(endTime);
843
//                  endTime = zTime.getTime();
844
//
845
//                  if(dateSysMetadataModified == null)
846
//                  {
847
//                      endDateComparison = 1;
848
//                  }
849
//                  else
850
//                  {
851
//                      endDateComparison = dateSysMetadataModified.compareTo(endTime);
852
//                  }
853
//                  //System.out.println("endDateCom: " + endDateComparison);
854
//              }
855
//              else
856
//              {
857
//                  endDateComparison = -1;
858
//              }
859
//
860
//
861
//              if(startDateComparison < 0 || endDateComparison > 0)
862
//              {
863
//                  continue;
864
//              }
865
//
866
//              docCopy.add((Document)docs.get(i));
867
//          } //end pre-parse
868
//
869
//          docs = docCopy;
870
//          totalAfterQuery = docs.size();
871
//          //System.out.println("total after subquery: " + totalAfterQuery);
872
//
873
//          //make sure we don't run over the end
874
//          int end = start + count;
875
//          if(end > docs.size())
876
//          {
877
//              end = docs.size();
878
//          }
879
//
880
//          for(int i=start; i<end; i++)
881
//          {
882
//              //get the document from the result
883
//              Document d = (Document)docs.get(i);
884
//              //System.out.println("processing doc " + d.docid);
885
//
886
//              String dateSMM = d.getField("dateSysMetadataModified");
887
//              //System.out.println("dateSMM: " + dateSMM);
888
//              //System.out.println("parsed date: " + parseDate(dateSMM));
889
//              Date dateSysMetadataModified = null;
890
//              if(dateSMM != null)
891
//              {
892
//                  try
893
//                  {
894
//                      dateSysMetadataModified = parseDate(dateSMM);
895
//                  }
896
//                  catch(Exception e)
897
//                  { //if we fail to parse the date, just ignore the value
898
//                      dateSysMetadataModified = null;
899
//                  }
900
//              }
901
//              ObjectFormat returnedObjectFormat = ObjectFormat.convert(d.getField("objectFormat"));
902
//
903
//
904
//              ObjectInfo info = new ObjectInfo();
905
//              //add the fields to the info object
906
//              Checksum cs = new Checksum();
907
//              cs.setValue(d.getField("checksum"));
908
//              String csalg = d.getField("algorithm");
909
//              if(csalg == null)
910
//              {
911
//                  csalg = "MD5";
912
//              }
913
//              ChecksumAlgorithm ca = ChecksumAlgorithm.convert(csalg);
914
//              cs.setAlgorithm(ca);
915
//              info.setChecksum(cs);
916
//              info.setDateSysMetadataModified(dateSysMetadataModified);
917
//              Identifier id = new Identifier();
918
//              id.setValue(d.getField("identifier").trim());
919
//              info.setIdentifier(id);
920
//              info.setObjectFormat(returnedObjectFormat);
921
//              String size = d.getField("size");
922
//              if(size != null)
923
//              {
924
//                  info.setSize(new Long(size.trim()).longValue());
925
//              }
926
//              //add the ObjectInfo to the ObjectList
927
//              //logCrud.info("objectFormat: " + info.getObjectFormat().toString());
928
//              //logCrud.info("id: " + info.getIdentifier().getValue());
929
//
930
//              if(info.getIdentifier().getValue() != null)
931
//              { //id can be null from tests.  should not happen in production.
932
//                  if((info.getObjectFormat() != null && !info.getObjectFormat().toString().trim().equals("")))
933
//                  { //objectFormat needs to not be null and not be an empty string
934
//                    ol.addObjectInfo(info);
935
//                  }
936
//                  else
937
//                  {
938
//                      logCrud.info("Not adding object with null objectFormat" + info.getIdentifier().getValue().toString());
939
//                  }
940
//              }
941
//
942
//          }
943
//      }
944
//      catch(Exception e)
945
//      {
946
//          e.printStackTrace();
947
//          logCrud.error("Error creating ObjectList: " + e.getMessage() + " cause: " + e.getCause());
948
//          throw new ServiceFailure("1580", "Error retrieving ObjectList: " + e.getMessage());
949
//      }
950
//      String username = "public";
951
//      if(sessionData != null)
952
//      {
953
//          username = sessionData.getUserName();
954
//      }
955
//      EventLog.getInstance().log(metacatUrl,
956
//              username, null, "read");
957
//      logCrud.info("listObjects");
958
//      if(totalAfterQuery < count)
959
//      {
960
//          count = totalAfterQuery;
961
//      }
962
//      ol.setCount(count);
963
//      ol.setStart(start);
964
//      ol.setTotal(totalAfterQuery);
965
//      return ol;
966 5359 berkley
    }
967
968
    /**
969
     * Call listObjects with the default values for replicaStatus (true), start (0),
970
     * and count (1000).
971
     * @param token
972
     * @param startTime
973
     * @param endTime
974
     * @param objectFormat
975
     * @return
976
     * @throws NotAuthorized
977
     * @throws InvalidRequest
978
     * @throws NotImplemented
979
     * @throws ServiceFailure
980
     * @throws InvalidToken
981
     */
982
    public ObjectList listObjects(AuthToken token, Date startTime, Date endTime,
983
        ObjectFormat objectFormat)
984
      throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
985
    {
986
       return listObjects(token, startTime, endTime, objectFormat, true, 0, 1000);
987
    }
988 5298 jones
989 5359 berkley
    /**
990 5654 berkley
     * Delete a document.
991 5359 berkley
     */
992 5320 jones
    public Identifier delete(AuthToken token, Identifier guid)
993 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
994 5654 berkley
            NotImplemented, InvalidRequest {
995 5392 berkley
        logCrud.info("delete");
996 5654 berkley
997
        if(token == null || token.getToken().equals("publid"))
998
        {
999
            throw new NotAuthorized("1320", "You must be logged in to delete records.");
1000
        }
1001
1002
        if(guid == null || guid.getValue().trim().equals(""))
1003
        {
1004
            throw new InvalidRequest("1322", "No GUID specified in CrudService.delete()");
1005
        }
1006
        final SessionData sessionData = getSessionData(token);
1007
        IdentifierManager manager = IdentifierManager.getInstance();
1008
1009
        String docid;
1010
        try
1011
        {
1012
            docid = manager.getLocalId(guid.getValue());
1013
        }
1014
        catch(McdbDocNotFoundException mnfe)
1015
        {
1016
            throw new InvalidRequest("1322", "GUID " + guid + " not found.");
1017
        }
1018
1019
        try
1020
        {
1021
            DocumentImpl.delete(docid, sessionData.getUserName(), sessionData.getGroupNames(), null);
1022
        }
1023 6001 cjones
        catch(SQLException e)
1024 5654 berkley
        {
1025
            throw new ServiceFailure("1350", "Could not delete document: " + e.getMessage());
1026
        }
1027 6001 cjones
        catch(McdbDocNotFoundException e)
1028
        {
1029
          throw new ServiceFailure("1350", "Could not delete document: " + e.getMessage());
1030
        }
1031
        catch(InsufficientKarmaException e)
1032
        {
1033
          throw new ServiceFailure("1350", "Could not delete document: " + e.getMessage());
1034
        }
1035
        catch(Exception e)
1036
        {
1037
          throw new ServiceFailure("1350", "Could not delete document: " + e.getMessage());
1038
        }
1039 5654 berkley
        return guid;
1040 5298 jones
    }
1041
1042 5359 berkley
    /**
1043 5648 berkley
     * describe a document.
1044 5359 berkley
     */
1045 5320 jones
    public DescribeResponse describe(AuthToken token, Identifier guid)
1046 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
1047 5648 berkley
            NotImplemented, InvalidRequest {
1048 5392 berkley
        logCrud.info("describe");
1049 5648 berkley
1050
        if(token == null)
1051
        {
1052
            throw new InvalidToken("1370", "Authentication token is null");
1053
        }
1054
1055
        if(guid == null || guid.getValue().trim().equals(""))
1056
        {
1057
            throw new InvalidRequest("1362", "Guid is null.  A valid guid is required.");
1058
        }
1059
1060
        SystemMetadata sm = getSystemMetadata(token, guid);
1061
        DescribeResponse dr = new DescribeResponse(sm.getObjectFormat(),
1062
                sm.getSize(), sm.getDateSysMetadataModified(), sm.getChecksum());
1063
        return dr;
1064 5298 jones
    }
1065
1066 5359 berkley
    /**
1067
     * get a document with a specified guid.
1068
     */
1069 5320 jones
    public InputStream get(AuthToken token, Identifier guid)
1070 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
1071
            NotImplemented {
1072
1073
        // Retrieve the session information from the AuthToken
1074
        // If the session is expired, then the user is 'public'
1075 5436 berkley
        if(token == null)
1076
        {
1077
            token = new AuthToken("Public");
1078
        }
1079 5298 jones
        final SessionData sessionData = getSessionData(token);
1080
1081
        // Look up the localId for this global identifier
1082
        IdentifierManager im = IdentifierManager.getInstance();
1083 5683 berkley
1084 5679 berkley
        try
1085
        {
1086 5320 jones
            final String localId = im.getLocalId(guid.getValue());
1087 5683 berkley
            InputStream objectStream;
1088 5679 berkley
            try
1089
            {
1090
                String username = "public";
1091
                String[] groups = new String[0];
1092
                if(sessionData != null)
1093
                {
1094
                    username = sessionData.getUserName();
1095
                    groups = sessionData.getGroupNames();
1096
                }
1097 5298 jones
1098 5683 berkley
                objectStream = readFromMetacat(localId, username, groups);
1099 5679 berkley
1100
            } catch (PropertyNotFoundException e) {
1101
                e.printStackTrace();
1102
                throw new ServiceFailure("1030", "Error getting property from metacat: " + e.getMessage());
1103
            } catch (ClassNotFoundException e) {
1104
                e.printStackTrace();
1105
                throw new ServiceFailure("1030", "Class not found error when reading from metacat: " + e.getMessage());
1106
            } catch (IOException e) {
1107
                e.printStackTrace();
1108
                throw new ServiceFailure("1030", "IOException while reading from metacat: " + e.getMessage());
1109
            } catch (SQLException e) {
1110
                e.printStackTrace();
1111
                throw new ServiceFailure("1030", "SQLException while reading from metacat: " + e.getMessage());
1112
            } catch (McdbException e) {
1113
                e.printStackTrace();
1114
                throw new ServiceFailure("1030", "Metacat DB exception while reading from metacat: " + e.getMessage());
1115
            } catch (ParseLSIDException e) {
1116
                e.printStackTrace();
1117
                throw new NotFound("1020", "LSID parsing exception while reading from metacat: " + e.getMessage());
1118
            } catch (InsufficientKarmaException e) {
1119
                e.printStackTrace();
1120
                throw new NotAuthorized("1000", "User not authorized for get(): " + e.getMessage());
1121
            }
1122
1123
1124 5431 berkley
            String username = "public";
1125
            if(sessionData != null)
1126
            {
1127
                username = sessionData.getUserName();
1128
            }
1129
1130 5383 berkley
            EventLog.getInstance().log(metacatUrl,
1131 5384 berkley
                    username, im.getLocalId(guid.getValue()), "read");
1132 5459 berkley
            logCrud.info("get D1GUID:" + guid.getValue() + ":D1SCIMETADATA:" + localId +
1133
                    ":");
1134 5680 berkley
1135 5298 jones
            return objectStream;
1136 5679 berkley
        }
1137
        catch (McdbDocNotFoundException e)
1138
        {
1139 5356 berkley
            throw new NotFound("1020", e.getMessage());
1140 5621 berkley
        }
1141 5298 jones
    }
1142
1143 5359 berkley
    /**
1144 5621 berkley
     * get the checksum for a document.  defaults to MD5.
1145 5359 berkley
     */
1146 5320 jones
    public Checksum getChecksum(AuthToken token, Identifier guid)
1147 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
1148 5621 berkley
            InvalidRequest, NotImplemented
1149
    {
1150 5392 berkley
        logCrud.info("getChecksum");
1151 5621 berkley
        return getChecksum(token, guid, "MD5");
1152 5298 jones
    }
1153
1154 5359 berkley
    /**
1155 5621 berkley
     * get the checksum for a document with the given algorithm
1156 5359 berkley
     */
1157 5320 jones
    public Checksum getChecksum(AuthToken token, Identifier guid,
1158 5298 jones
            String checksumAlgorithm) throws InvalidToken, ServiceFailure,
1159 5621 berkley
            NotAuthorized, NotFound, InvalidRequest, NotImplemented
1160
    {
1161 5392 berkley
        logCrud.info("getChecksum");
1162 5670 berkley
        SystemMetadata sm = getSystemMetadata(token, guid);
1163
        Checksum cs = sm.getChecksum();
1164
        if(cs.getAlgorithm().toString().equals(checksumAlgorithm))
1165 5644 berkley
        {
1166 5670 berkley
            return cs;
1167 5644 berkley
        }
1168 5670 berkley
        else
1169 5621 berkley
        {
1170 5670 berkley
            if(checksumAlgorithm == null)
1171
            {
1172
                checksumAlgorithm = "MD5";
1173
            }
1174
            InputStream docStream = get(token, guid);
1175
            String checksum;
1176
            try
1177
            {
1178
                checksum = checksum(docStream, checksumAlgorithm);
1179
            }
1180
            catch(Exception e)
1181
            {
1182
                throw new ServiceFailure("1410", "Error getting checksum: " + e.getMessage());
1183
            }
1184
            Checksum c = new Checksum();
1185
            c.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
1186
            c.setValue(checksum);
1187
            return c;
1188 5621 berkley
        }
1189 5298 jones
    }
1190
1191 5359 berkley
    /**
1192 5384 berkley
     * get log records.
1193 5359 berkley
     */
1194 5390 berkley
    public Log getLogRecords(AuthToken token, Date fromDate, Date toDate, Event event)
1195 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, InvalidRequest,
1196 5384 berkley
            NotImplemented
1197
    {
1198 5630 berkley
        /*System.out.println("=================== Getting log records ===================");
1199 5430 berkley
        System.out.println("Current server time is: " + new Date());
1200
        if(fromDate != null)
1201
        {
1202
          System.out.println("query start time is " + fromDate);
1203
        }
1204
        if(toDate != null)
1205
        {
1206
          System.out.println("query end time is " + toDate);
1207 5630 berkley
        }*/
1208 5389 berkley
        Log log = new Log();
1209
        Vector<LogEntry> logs = new Vector<LogEntry>();
1210 5384 berkley
        IdentifierManager im = IdentifierManager.getInstance();
1211
        EventLog el = EventLog.getInstance();
1212 5391 berkley
        if(fromDate == null)
1213
        {
1214 5630 berkley
            //System.out.println("setting fromdate from null");
1215 5391 berkley
            fromDate = new Date(1);
1216
        }
1217
        if(toDate == null)
1218
        {
1219 5630 berkley
            //System.out.println("setting todate from null");
1220 5391 berkley
            toDate = new Date();
1221
        }
1222 5418 berkley
1223 5630 berkley
        //System.out.println("fromDate: " + fromDate);
1224
        //System.out.println("toDate: " + toDate);
1225 5418 berkley
1226 5384 berkley
        String report = el.getReport(null, null, null, null,
1227
                new java.sql.Timestamp(fromDate.getTime()),
1228 5693 leinfelder
                new java.sql.Timestamp(toDate.getTime()), false);
1229 5384 berkley
1230 5418 berkley
        //System.out.println("report: " + report);
1231
1232 5384 berkley
        String logEntry = "<logEntry>";
1233
        String endLogEntry = "</logEntry>";
1234
        int startIndex = 0;
1235
        int foundIndex = report.indexOf(logEntry, startIndex);
1236
        while(foundIndex != -1)
1237
        {
1238
            //parse out each entry
1239
            int endEntryIndex = report.indexOf(endLogEntry, foundIndex);
1240
            String entry = report.substring(foundIndex, endEntryIndex);
1241
            //System.out.println("entry: " + entry);
1242
            startIndex = endEntryIndex + endLogEntry.length();
1243
            foundIndex = report.indexOf(logEntry, startIndex);
1244
1245
            String entryId = getLogEntryField("entryid", entry);
1246
            String ipAddress = getLogEntryField("ipAddress", entry);
1247
            String principal = getLogEntryField("principal", entry);
1248
            String docid = getLogEntryField("docid", entry);
1249 5390 berkley
            String eventS = getLogEntryField("event", entry);
1250 5384 berkley
            String dateLogged = getLogEntryField("dateLogged", entry);
1251
1252 5389 berkley
            LogEntry le = new LogEntry();
1253 5384 berkley
1254 5390 berkley
            Event e = Event.convert(eventS);
1255 5384 berkley
            if(e == null)
1256
            { //skip any events that are not Dataone Crud events
1257
                continue;
1258
            }
1259 5389 berkley
            le.setEvent(e);
1260 5384 berkley
            Identifier entryid = new Identifier();
1261
            entryid.setValue(entryId);
1262 5389 berkley
            le.setEntryId(entryid);
1263 5384 berkley
            Identifier identifier = new Identifier();
1264
            try
1265
            {
1266 5432 berkley
                //System.out.println("converting docid '" + docid + "' to a guid.");
1267 5417 berkley
                if(docid == null || docid.trim().equals("") || docid.trim().equals("null"))
1268
                {
1269
                    continue;
1270
                }
1271 5416 berkley
                docid = docid.substring(0, docid.lastIndexOf("."));
1272 5384 berkley
                identifier.setValue(im.getGUID(docid, im.getLatestRevForLocalId(docid)));
1273
            }
1274
            catch(Exception ex)
1275
            { //try to get the guid, if that doesn't work, just use the local id
1276 5419 berkley
                //throw new ServiceFailure("1030", "Error getting guid for localId " +
1277 5424 berkley
                //        docid + ": " + ex.getMessage());\
1278
1279
                //skip it if the guid can't be found
1280 5419 berkley
                continue;
1281 5384 berkley
            }
1282
1283 5389 berkley
            le.setIdentifier(identifier);
1284
            le.setIpAddress(ipAddress);
1285 5384 berkley
            Calendar c = Calendar.getInstance();
1286
            String year = dateLogged.substring(0, 4);
1287
            String month = dateLogged.substring(5, 7);
1288
            String date = dateLogged.substring(8, 10);
1289
            //System.out.println("year: " + year + " month: " + month + " day: " + date);
1290
            c.set(new Integer(year).intValue(), new Integer(month).intValue(), new Integer(date).intValue());
1291
            Date logDate = c.getTime();
1292 5389 berkley
            le.setDateLogged(logDate);
1293 5384 berkley
            NodeReference memberNode = new NodeReference();
1294
            memberNode.setValue(ipAddress);
1295 5389 berkley
            le.setMemberNode(memberNode);
1296 5384 berkley
            Principal princ = new Principal();
1297
            princ.setValue(principal);
1298 5389 berkley
            le.setPrincipal(princ);
1299
            le.setUserAgent("metacat/RESTService");
1300 5390 berkley
1301
            if(event == null)
1302
            {
1303
                logs.add(le);
1304
            }
1305
1306
            if(event != null &&
1307
               e.toString().toLowerCase().trim().equals(event.toString().toLowerCase().trim()))
1308
            {
1309
              logs.add(le);
1310
            }
1311 5384 berkley
        }
1312
1313 5389 berkley
        log.setLogEntryList(logs);
1314 5392 berkley
        logCrud.info("getLogRecords");
1315 5389 berkley
        return log;
1316 5298 jones
    }
1317 5384 berkley
1318
    /**
1319
     * parse a logEntry and get the relavent field from it
1320
     * @param fieldname
1321
     * @param entry
1322
     * @return
1323
     */
1324
    private String getLogEntryField(String fieldname, String entry)
1325
    {
1326
        String begin = "<" + fieldname + ">";
1327
        String end = "</" + fieldname + ">";
1328
        //System.out.println("looking for " + begin + " and " + end + " in entry " + entry);
1329
        String s = entry.substring(entry.indexOf(begin) + begin.length(), entry.indexOf(end));
1330
        //System.out.println("entry " + fieldname + " : " + s);
1331
        return s;
1332
    }
1333 5298 jones
1334 5359 berkley
    /**
1335
     * get the system metadata for a document with a specified guid.
1336
     */
1337 5481 berkley
public SystemMetadata getSystemMetadata(AuthToken token, Identifier guid)
1338 5298 jones
            throws InvalidToken, ServiceFailure, NotAuthorized, NotFound,
1339
            InvalidRequest, NotImplemented {
1340 5319 jones
1341 5332 jones
        logMetacat.debug("CrudService.getSystemMetadata - for guid: " + guid.getValue());
1342
1343
        // Retrieve the session information from the AuthToken
1344
        // If the session is expired, then the user is 'public'
1345
        final SessionData sessionData = getSessionData(token);
1346
1347
        try {
1348
            IdentifierManager im = IdentifierManager.getInstance();
1349 5424 berkley
            final String localId = im.getSystemMetadataLocalId(guid.getValue());
1350 5683 berkley
            InputStream objectStream;
1351 5332 jones
1352 5683 berkley
            try {
1353
                String username = "public";
1354
                String[] groupnames = null;
1355
                if(sessionData != null)
1356
                {
1357
                    username = sessionData.getUserName();
1358
                    groupnames = sessionData.getGroupNames();
1359
                }
1360 5332 jones
1361 5683 berkley
                objectStream = readFromMetacat(localId, username, groupnames);
1362
1363
            } catch (PropertyNotFoundException e) {
1364
                e.printStackTrace();
1365
                throw new ServiceFailure("1090", "Property not found while reading system metadata from metacat: " + e.getMessage());
1366
            } catch (ClassNotFoundException e) {
1367
                e.printStackTrace();
1368
                throw new ServiceFailure("1090", "Class not found while reading system metadata from metacat: " + e.getMessage());
1369
            } catch (IOException e) {
1370
                e.printStackTrace();
1371
                throw new ServiceFailure("1090", "IOException while reading system metadata from metacat: " + e.getMessage());
1372
            } catch (SQLException e) {
1373
                e.printStackTrace();
1374
                throw new ServiceFailure("1090", "SQLException while reading system metadata from metacat: " + e.getMessage());
1375
            } catch (McdbException e) {
1376
                e.printStackTrace();
1377
                throw new ServiceFailure("1090", "Metacat DB Exception while reading system metadata from metacat: " + e.getMessage());
1378
            } catch (ParseLSIDException e) {
1379
                e.printStackTrace();
1380
                throw new NotFound("1060", "Error parsing LSID while reading system metadata from metacat: " + e.getMessage());
1381
            } catch (InsufficientKarmaException e) {
1382
                e.printStackTrace();
1383
                throw new NotAuthorized("1040", "User not authorized for get() on system metadata: " + e.getMessage());
1384
            }
1385 5449 berkley
1386 5332 jones
            // Deserialize the xml to create a SystemMetadata object
1387
            SystemMetadata sysmeta = deserializeSystemMetadata(objectStream);
1388 5431 berkley
            String username = "public";
1389
            if(sessionData != null)
1390
            {
1391
                username = sessionData.getUserName();
1392
            }
1393 5383 berkley
            EventLog.getInstance().log(metacatUrl,
1394 5384 berkley
                    username, im.getLocalId(guid.getValue()), "read");
1395 5459 berkley
            logCrud.info("getsystemmetadata D1GUID:" + guid.getValue()  +
1396 5582 berkley
                    ":D1SYSMETADATA:"+ localId + ":");
1397 5332 jones
            return sysmeta;
1398
1399
        } catch (McdbDocNotFoundException e) {
1400 5348 berkley
            //e.printStackTrace();
1401 5624 berkley
            throw new NotFound("1040", e.getMessage());
1402 5332 jones
        }
1403 5298 jones
    }
1404 5366 berkley
1405
    /**
1406
     * parse the date in the systemMetadata
1407
     * @param s
1408
     * @return
1409
     * @throws Exception
1410
     */
1411 5418 berkley
    public Date parseDate(String s)
1412 5366 berkley
      throws Exception
1413
    {
1414 5466 berkley
        /* TODO:
1415
         * This method should be replaced by a DateFormatter
1416
         */
1417 5366 berkley
        Date d = null;
1418
        int tIndex = s.indexOf("T");
1419
        int zIndex = s.indexOf("Z");
1420
        if(tIndex != -1 && zIndex != -1)
1421
        { //parse a date that looks like 2010-05-18T21:12:54.362Z
1422
            //System.out.println("original date: " + s);
1423
1424
            String date = s.substring(0, tIndex);
1425
            String year = date.substring(0, date.indexOf("-"));
1426
            String month = date.substring(date.indexOf("-") + 1, date.lastIndexOf("-"));
1427
            String day = date.substring(date.lastIndexOf("-") + 1, date.length());
1428
            /*System.out.println("date: " + "year: " + new Integer(year).intValue() +
1429
                    " month: " + new Integer(month).intValue() + " day: " +
1430
                    new Integer(day).intValue());
1431
            */
1432
            String time = s.substring(tIndex + 1, zIndex);
1433
            String hour = time.substring(0, time.indexOf(":"));
1434
            String minute = time.substring(time.indexOf(":") + 1, time.lastIndexOf(":"));
1435
            String seconds = "00";
1436
            String milliseconds = "00";
1437
            if(time.indexOf(".") != -1)
1438
            {
1439
                seconds = time.substring(time.lastIndexOf(":") + 1, time.indexOf("."));
1440
                milliseconds = time.substring(time.indexOf(".") + 1, time.length());
1441
            }
1442 5418 berkley
            else
1443
            {
1444
                seconds = time.substring(time.lastIndexOf(":") + 1, time.length());
1445
            }
1446 5366 berkley
            /*System.out.println("time: " + "hour: " + new Integer(hour).intValue() +
1447
                    " minute: " + new Integer(minute).intValue() + " seconds: " +
1448
                    new Integer(seconds).intValue() + " milli: " +
1449
                    new Integer(milliseconds).intValue());*/
1450
1451
            //d = DateFormat.getDateTimeInstance().parse(date + " " + time);
1452 5630 berkley
            Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT-0")/*TimeZone.getDefault()*/);
1453 5366 berkley
            c.set(new Integer(year).intValue(), new Integer(month).intValue() - 1,
1454
                  new Integer(day).intValue(), new Integer(hour).intValue(),
1455
                  new Integer(minute).intValue(), new Integer(seconds).intValue());
1456
            c.set(Calendar.MILLISECOND, new Integer(milliseconds).intValue());
1457
            d = new Date(c.getTimeInMillis());
1458
            //System.out.println("d: " + d);
1459
            return d;
1460
        }
1461
        else
1462
        {  //if it's not in the expected format, try the formatter
1463
            return DateFormat.getDateTimeInstance().parse(s);
1464
        }
1465
    }
1466 5298 jones
1467 5331 jones
    /*
1468
     * Look up the information on the session using the token provided in
1469
     * the AuthToken.  The Session should have all relevant user information.
1470
     * If the session has expired or is invalid, the 'public' session will
1471
     * be returned, giving the user anonymous access.
1472
     */
1473 5394 berkley
    public static SessionData getSessionData(AuthToken token) {
1474 5331 jones
        SessionData sessionData = null;
1475
        String sessionId = "PUBLIC";
1476
        if (token != null) {
1477
            sessionId = token.getToken();
1478
        }
1479
1480
        // if the session id is registered in SessionService, get the
1481
        // SessionData for it. Otherwise, use the public session.
1482 5411 berkley
        //System.out.println("sessionid: " + sessionId);
1483 5403 berkley
        if (sessionId != null &&
1484 5406 berkley
            !sessionId.toLowerCase().equals("public") &&
1485 5403 berkley
            SessionService.getInstance().isSessionRegistered(sessionId))
1486
        {
1487 5374 berkley
            sessionData = SessionService.getInstance().getRegisteredSession(sessionId);
1488 5331 jones
        } else {
1489 5374 berkley
            sessionData = SessionService.getInstance().getPublicSession();
1490 5331 jones
        }
1491 5411 berkley
1492 5331 jones
        return sessionData;
1493
    }
1494
1495
    /**
1496
     * Determine if a given object should be treated as an XML science metadata
1497
     * object.
1498
     *
1499
     * TODO: This test should be externalized in a configuration dictionary rather than being hardcoded.
1500
     *
1501
     * @param sysmeta the SystemMetadata describig the object
1502
     * @return true if the object should be treated as science metadata
1503
     */
1504
    private boolean isScienceMetadata(SystemMetadata sysmeta) {
1505 5523 berkley
        /*boolean scimeta = false;
1506 5466 berkley
        //TODO: this should be read from a .properties file instead of being hard coded
1507 5331 jones
        switch (sysmeta.getObjectFormat()) {
1508
            case EML_2_1_0: scimeta = true; break;
1509
            case EML_2_0_1: scimeta = true; break;
1510
            case EML_2_0_0: scimeta = true; break;
1511
            case FGDC_STD_001_1_1999: scimeta = true; break;
1512
            case FGDC_STD_001_1998: scimeta = true; break;
1513
            case NCML_2_2: scimeta = true; break;
1514 5521 berkley
            case DSPACE_METS_SIP_1_0: scimeta = true; break;
1515 5331 jones
        }
1516
1517 5523 berkley
        return scimeta;*/
1518
1519
        return MetadataTypeRegister.isMetadataType(sysmeta.getObjectFormat());
1520 5331 jones
    }
1521
1522 5359 berkley
    /**
1523
     * insert a data doc
1524
     * @param object
1525
     * @param guid
1526
     * @param sessionData
1527
     * @throws ServiceFailure
1528 5459 berkley
     * @returns localId of the data object inserted
1529 5359 berkley
     */
1530 5459 berkley
    private String insertDataObject(InputStream object, Identifier guid,
1531 5331 jones
            SessionData sessionData) throws ServiceFailure {
1532
1533 5431 berkley
        String username = "public";
1534
        String[] groups = null;
1535
        if(sessionData != null)
1536
        {
1537
          username = sessionData.getUserName();
1538
          groups = sessionData.getGroupNames();
1539
        }
1540 5331 jones
1541
        // generate guid/localId pair for object
1542
        logMetacat.debug("Generating a guid/localId mapping");
1543
        IdentifierManager im = IdentifierManager.getInstance();
1544
        String localId = im.generateLocalId(guid.getValue(), 1);
1545
1546
        try {
1547
            logMetacat.debug("Case DATA: starting to write to disk.");
1548
            if (DocumentImpl.getDataFileLockGrant(localId)) {
1549
1550
                // Save the data file to disk using "localId" as the name
1551
                try {
1552
                    String datafilepath = PropertyService.getProperty("application.datafilepath");
1553
1554
                    File dataDirectory = new File(datafilepath);
1555
                    dataDirectory.mkdirs();
1556
1557
                    File newFile = writeStreamToFile(dataDirectory, localId, object);
1558
1559
                    // TODO: Check that the file size matches SystemMetadata
1560
                    //                        long size = newFile.length();
1561
                    //                        if (size == 0) {
1562
                    //                            throw new IOException("Uploaded file is 0 bytes!");
1563
                    //                        }
1564
1565
                    // Register the file in the database (which generates an exception
1566
                    // if the localId is not acceptable or other untoward things happen
1567
                    try {
1568
                        logMetacat.debug("Registering document...");
1569
                        DocumentImpl.registerDocument(localId, "BIN", localId,
1570
                                username, groups);
1571
                        logMetacat.debug("Registration step completed.");
1572
                    } catch (SQLException e) {
1573
                        //newFile.delete();
1574
                        logMetacat.debug("SQLE: " + e.getMessage());
1575
                        e.printStackTrace(System.out);
1576 5356 berkley
                        throw new ServiceFailure("1190", "Registration failed: " + e.getMessage());
1577 5331 jones
                    } catch (AccessionNumberException e) {
1578
                        //newFile.delete();
1579
                        logMetacat.debug("ANE: " + e.getMessage());
1580
                        e.printStackTrace(System.out);
1581 5356 berkley
                        throw new ServiceFailure("1190", "Registration failed: " + e.getMessage());
1582 5331 jones
                    } catch (Exception e) {
1583
                        //newFile.delete();
1584
                        logMetacat.debug("Exception: " + e.getMessage());
1585
                        e.printStackTrace(System.out);
1586 5356 berkley
                        throw new ServiceFailure("1190", "Registration failed: " + e.getMessage());
1587 5331 jones
                    }
1588
1589
                    logMetacat.debug("Logging the creation event.");
1590 5344 berkley
                    EventLog.getInstance().log(metacatUrl,
1591 5384 berkley
                            username, localId, "create");
1592 5331 jones
1593
                    // Schedule replication for this data file
1594
                    logMetacat.debug("Scheduling replication.");
1595
                    ForceReplicationHandler frh = new ForceReplicationHandler(
1596 5384 berkley
                            localId, "create", false, null);
1597 5331 jones
1598
                } catch (PropertyNotFoundException e) {
1599 5356 berkley
                    throw new ServiceFailure("1190", "Could not lock file for writing:" + e.getMessage());
1600 5331 jones
                }
1601
            }
1602 5459 berkley
            return localId;
1603 5331 jones
        } catch (Exception e) {
1604
            // Could not get a lock on the document, so we can not update the file now
1605 5356 berkley
            throw new ServiceFailure("1190", "Failed to lock file: " + e.getMessage());
1606 5331 jones
        }
1607
    }
1608
1609 5359 berkley
    /**
1610
     * write a file to a stream
1611
     * @param dir
1612
     * @param fileName
1613
     * @param data
1614
     * @return
1615
     * @throws ServiceFailure
1616
     */
1617 5319 jones
    private File writeStreamToFile(File dir, String fileName, InputStream data)
1618
        throws ServiceFailure {
1619
1620
        File newFile = new File(dir, fileName);
1621
        logMetacat.debug("Filename for write is: " + newFile.getAbsolutePath());
1622
1623
        try {
1624
            if (newFile.createNewFile()) {
1625
                // write data stream to desired file
1626
                OutputStream os = new FileOutputStream(newFile);
1627
                long length = IOUtils.copyLarge(data, os);
1628
                os.flush();
1629
                os.close();
1630
            } else {
1631
                logMetacat.debug("File creation failed, or file already exists.");
1632 5356 berkley
                throw new ServiceFailure("1190", "File already exists: " + fileName);
1633 5319 jones
            }
1634
        } catch (FileNotFoundException e) {
1635
            logMetacat.debug("FNF: " + e.getMessage());
1636 5356 berkley
            throw new ServiceFailure("1190", "File not found: " + fileName + " "
1637 5319 jones
                    + e.getMessage());
1638
        } catch (IOException e) {
1639
            logMetacat.debug("IOE: " + e.getMessage());
1640 5356 berkley
            throw new ServiceFailure("1190", "File was not written: " + fileName
1641 5319 jones
                    + " " + e.getMessage());
1642
        }
1643
1644
        return newFile;
1645 5329 jones
    }
1646
1647 5350 berkley
    /**
1648 5441 berkley
     * insert a systemMetadata doc, return the localId of the sysmeta
1649 5350 berkley
     */
1650 5441 berkley
    private String insertSystemMetadata(SystemMetadata sysmeta, SessionData sessionData)
1651 5377 berkley
        throws ServiceFailure
1652
    {
1653 5329 jones
        logMetacat.debug("Starting to insert SystemMetadata...");
1654
1655
        // generate guid/localId pair for sysmeta
1656 5331 jones
        Identifier sysMetaGuid = new Identifier();
1657
        sysMetaGuid.setValue(DocumentUtil.generateDocumentId(1));
1658 5329 jones
        sysmeta.setDateSysMetadataModified(new Date());
1659 5953 cjones
        logCrud.debug("****inserting new system metadata with modified date " +
1660 5453 berkley
                sysmeta.getDateSysMetadataModified());
1661 5329 jones
1662
        String xml = new String(serializeSystemMetadata(sysmeta).toByteArray());
1663 5953 cjones
        logCrud.debug("sysmeta: " + xml);
1664 5453 berkley
        String localId = insertDocument(xml, sysMetaGuid, sessionData, true);
1665 5953 cjones
        logCrud.debug("sysmeta inserted with localId " + localId);
1666 5453 berkley
        //insert the system metadata doc id into the systemmetadata table to
1667 5333 berkley
        //link it to the data or metadata document
1668 5377 berkley
        IdentifierManager.getInstance().createSystemMetadataMapping(
1669 5887 berkley
                sysmeta, sysMetaGuid.getValue());
1670 5441 berkley
        return localId;
1671 5329 jones
    }
1672
1673 5333 berkley
    /**
1674 5350 berkley
     * update a systemMetadata doc
1675
     */
1676
    private void updateSystemMetadata(SystemMetadata sm, SessionData sessionData)
1677
      throws ServiceFailure
1678
    {
1679 5953 cjones
1680
        logCrud.debug("CrudService.updateSystemMetadata() called.");
1681 5350 berkley
        try
1682
        {
1683 5424 berkley
            String smId = IdentifierManager.getInstance().getSystemMetadataLocalId(sm.getIdentifier().getValue());
1684 5953 cjones
            logCrud.debug("Setting date modified to " + new Date());
1685 5350 berkley
            sm.setDateSysMetadataModified(new Date());
1686
            String xml = new String(serializeSystemMetadata(sm).toByteArray());
1687 5456 berkley
            String localId = updateDocument(xml, sm.getIdentifier(), null, sessionData, true);
1688 5350 berkley
            IdentifierManager.getInstance().updateSystemMetadataMapping(sm.getIdentifier().getValue(), localId);
1689 5953 cjones
            IdentifierManager.getInstance().insertAdditionalSystemMetadataFields(
1690
              sm.getDateUploaded().getTime(),
1691
              sm.getRightsHolder().getValue(),
1692
              sm.getChecksum().getValue(),
1693 5957 berkley
              /*sm.getChecksum().getAlgorithm().toString()*/sm.getChecksum().getAlgorithm().name(),
1694 5953 cjones
              sm.getOriginMemberNode().getValue(),
1695
              sm.getAuthoritativeMemberNode().getValue(),
1696
              sm.getDateSysMetadataModified().getTime(),
1697
              sm.getSubmitter().getValue(),
1698
              sm.getIdentifier().getValue(),
1699
              sm.getObjectFormat().toString(),
1700
              sm.getSize());
1701
1702 5350 berkley
        }
1703
        catch(Exception e)
1704
        {
1705 6068 rnahf
            throw new ServiceFailure("1030", "Error updating system metadata: " + e.getClass() + ": " + e.getMessage());
1706 5350 berkley
        }
1707
    }
1708
1709 5453 berkley
    private String insertDocument(String xml, Identifier guid, SessionData sessionData)
1710
        throws ServiceFailure
1711
    {
1712
        return insertDocument(xml, guid, sessionData, false);
1713
    }
1714
1715 5350 berkley
    /**
1716
     * insert a document
1717
     * NOTE: this method shouldn't be used from the update or create() methods.
1718
     * we shouldn't be putting the science metadata or data objects into memory.
1719
     */
1720 5453 berkley
    private String insertDocument(String xml, Identifier guid, SessionData sessionData,
1721
            boolean isSystemMetadata)
1722 5350 berkley
        throws ServiceFailure
1723
    {
1724 5453 berkley
        return insertOrUpdateDocument(xml, guid, sessionData, "insert", isSystemMetadata);
1725 5350 berkley
    }
1726
1727
    /**
1728
     * insert a document from a stream
1729
     */
1730
    private String insertDocument(InputStream is, Identifier guid, SessionData sessionData)
1731
      throws IOException, ServiceFailure
1732
    {
1733
        //HACK: change this eventually.  we should not be converting the stream to a string
1734
        String xml = IOUtils.toString(is);
1735
        return insertDocument(xml, guid, sessionData);
1736
    }
1737
1738
    /**
1739
     * update a document
1740
     * NOTE: this method shouldn't be used from the update or create() methods.
1741
     * we shouldn't be putting the science metadata or data objects into memory.
1742
     */
1743 5453 berkley
    private String updateDocument(String xml, Identifier obsoleteGuid,
1744
            Identifier guid, SessionData sessionData, boolean isSystemMetadata)
1745 5350 berkley
        throws ServiceFailure
1746
    {
1747 5453 berkley
        return insertOrUpdateDocument(xml, obsoleteGuid, sessionData, "update", isSystemMetadata);
1748 5350 berkley
    }
1749
1750
    /**
1751
     * update a document from a stream
1752
     */
1753 5453 berkley
    private String updateDocument(InputStream is, Identifier obsoleteGuid,
1754
            Identifier guid, SessionData sessionData, boolean isSystemMetadata)
1755 5350 berkley
      throws IOException, ServiceFailure
1756
    {
1757
        //HACK: change this eventually.  we should not be converting the stream to a string
1758
        String xml = IOUtils.toString(is);
1759 5453 berkley
        String localId = updateDocument(xml, obsoleteGuid, guid, sessionData, isSystemMetadata);
1760 5350 berkley
        IdentifierManager im = IdentifierManager.getInstance();
1761
        if(guid != null)
1762
        {
1763
          im.createMapping(guid.getValue(), localId);
1764
        }
1765
        return localId;
1766
    }
1767
1768
    /**
1769 5333 berkley
     * insert a document, return the id of the document that was inserted
1770
     */
1771 5453 berkley
    protected String insertOrUpdateDocument(String xml, Identifier guid,
1772
            SessionData sessionData, String insertOrUpdate, boolean isSystemMetadata)
1773 5329 jones
        throws ServiceFailure {
1774
        logMetacat.debug("Starting to insert xml document...");
1775
        IdentifierManager im = IdentifierManager.getInstance();
1776
1777
        // generate guid/localId pair for sysmeta
1778 5350 berkley
        String localId = null;
1779
        if(insertOrUpdate.equals("insert"))
1780
        {
1781 5453 berkley
            localId = im.generateLocalId(guid.getValue(), 1, isSystemMetadata);
1782 5350 berkley
        }
1783
        else
1784
        {
1785
            //localid should already exist in the identifier table, so just find it
1786
            try
1787
            {
1788 5953 cjones
                logCrud.debug("updating guid " + guid.getValue());
1789 5456 berkley
                if(!isSystemMetadata)
1790
                {
1791 5953 cjones
                    logCrud.debug("looking in identifier table for guid " + guid.getValue());
1792 5456 berkley
                    localId = im.getLocalId(guid.getValue());
1793
                }
1794
                else
1795
                {
1796 5953 cjones
                    logCrud.debug("looking in systemmetadata table for guid " + guid.getValue());
1797 5456 berkley
                    localId = im.getSystemMetadataLocalId(guid.getValue());
1798
                }
1799 5953 cjones
                logCrud.debug("localId: " + localId);
1800 5350 berkley
                //increment the revision
1801
                String docid = localId.substring(0, localId.lastIndexOf("."));
1802
                String revS = localId.substring(localId.lastIndexOf(".") + 1, localId.length());
1803
                int rev = new Integer(revS).intValue();
1804
                rev++;
1805
                docid = docid + "." + rev;
1806
                localId = docid;
1807 5953 cjones
                logCrud.debug("incremented localId: " + localId);
1808 5350 berkley
            }
1809
            catch(McdbDocNotFoundException e)
1810
            {
1811 5356 berkley
                throw new ServiceFailure("1030", "CrudService.insertOrUpdateDocument(): " +
1812 5350 berkley
                    "guid " + guid.getValue() + " should have been in the identifier table, but it wasn't: " + e.getMessage());
1813
            }
1814
        }
1815 5331 jones
        logMetacat.debug("Metadata guid|localId: " + guid.getValue() + "|" +
1816 5329 jones
                localId);
1817
1818
        String[] action = new String[1];
1819 5350 berkley
        action[0] = insertOrUpdate;
1820 5329 jones
        params.put("action", action);
1821
        String[] docid = new String[1];
1822
        docid[0] = localId;
1823
        params.put("docid", docid);
1824
        String[] doctext = new String[1];
1825
        doctext[0] = xml;
1826
        logMetacat.debug(doctext[0]);
1827
        params.put("doctext", doctext);
1828 5331 jones
1829
        // TODO: refactor handleInsertOrUpdateAction() to not output XML directly
1830
        // onto output stream, or alternatively, capture that and parse it to
1831
        // generate the right exceptions
1832 5337 berkley
        //ByteArrayOutputStream output = new ByteArrayOutputStream();
1833
        //PrintWriter pw = new PrintWriter(output);
1834 5449 berkley
        String username = "public";
1835
        String[] groupnames = null;
1836
        if(sessionData != null)
1837
        {
1838
            username = sessionData.getUserName();
1839
            groupnames = sessionData.getGroupNames();
1840
        }
1841 5344 berkley
        String result = handler.handleInsertOrUpdateAction(metacatUrl, null,
1842 5449 berkley
                            null, params, username, groupnames);
1843 5461 berkley
        if(result.indexOf("<error>") != -1)
1844
        {
1845
            throw new ServiceFailure("1000", "Error inserting or updating document: " + result);
1846
        }
1847 5337 berkley
        //String outputS = new String(output.toByteArray());
1848
        logMetacat.debug("CrudService.insertDocument - Metacat returned: " + result);
1849 5333 berkley
        logMetacat.debug("Finsished inserting xml document with id " + localId);
1850
        return localId;
1851 5329 jones
    }
1852
1853 5359 berkley
    /**
1854 5555 berkley
     * serialize a dataone type
1855 5550 berkley
     */
1856 5921 jones
//    private void serializeServiceType(Class type, Object object, OutputStream out)
1857
//        throws JiBXException
1858
//    {
1859
//        IBindingFactory bfact = BindingDirectory.getFactory(type);
1860
//        IMarshallingContext mctx = bfact.createMarshallingContext();
1861
//        mctx.marshalDocument(object, "UTF-8", null, out);
1862
//    }
1863 5550 berkley
1864
    /**
1865 5359 berkley
     * serialize a system metadata doc
1866
     * @param sysmeta
1867
     * @return
1868
     * @throws ServiceFailure
1869
     */
1870 5332 jones
    public static ByteArrayOutputStream serializeSystemMetadata(SystemMetadata sysmeta)
1871 5329 jones
        throws ServiceFailure {
1872
        IBindingFactory bfact;
1873
        ByteArrayOutputStream sysmetaOut = null;
1874
        try {
1875
            bfact = BindingDirectory.getFactory(SystemMetadata.class);
1876
            IMarshallingContext mctx = bfact.createMarshallingContext();
1877
            sysmetaOut = new ByteArrayOutputStream();
1878
            mctx.marshalDocument(sysmeta, "UTF-8", null, sysmetaOut);
1879
        } catch (JiBXException e) {
1880 5382 berkley
            e.printStackTrace();
1881 5356 berkley
            throw new ServiceFailure("1190", "Failed to serialize and insert SystemMetadata: " + e.getMessage());
1882 5329 jones
        }
1883
1884
        return sysmetaOut;
1885
    }
1886 5332 jones
1887 5359 berkley
    /**
1888
     * deserialize a system metadata doc
1889
     * @param xml
1890
     * @return
1891
     * @throws ServiceFailure
1892
     */
1893 5332 jones
    public static SystemMetadata deserializeSystemMetadata(InputStream xml)
1894
        throws ServiceFailure {
1895
        try {
1896
            IBindingFactory bfact = BindingDirectory.getFactory(SystemMetadata.class);
1897
            IUnmarshallingContext uctx = bfact.createUnmarshallingContext();
1898
            SystemMetadata sysmeta = (SystemMetadata) uctx.unmarshalDocument(xml, null);
1899
            return sysmeta;
1900
        } catch (JiBXException e) {
1901 5382 berkley
            e.printStackTrace();
1902
            throw new ServiceFailure("1190", "Failed to deserialize and insert SystemMetadata: " + e.getMessage());
1903 5332 jones
        }
1904
    }
1905 5378 berkley
1906
    /**
1907 5683 berkley
     * read a document from metacat and return the InputStream
1908
     *
1909
     * @param localId
1910
     * @param username
1911
     * @param groups
1912
     * @return
1913
     * @throws InsufficientKarmaException
1914
     * @throws ParseLSIDException
1915
     * @throws PropertyNotFoundException
1916
     * @throws McdbException
1917
     * @throws SQLException
1918
     * @throws ClassNotFoundException
1919
     * @throws IOException
1920
     */
1921
    private InputStream readFromMetacat(String localId, String username, String[] groups)
1922
        throws InsufficientKarmaException, ParseLSIDException,
1923
        PropertyNotFoundException, McdbException, SQLException,
1924
        ClassNotFoundException, IOException
1925
    {
1926
        File tmpDir;
1927
        try
1928
        {
1929
            tmpDir = new File(PropertyService.getProperty("application.tempDir"));
1930
        }
1931
        catch(PropertyNotFoundException pnfe)
1932
        {
1933
            logMetacat.error("ResourceHandler.writeMMPPartstoFiles: " +
1934
                    "application.tmpDir not found.  Using /tmp instead.");
1935
            tmpDir = new File("/tmp");
1936
        }
1937
        Date d = new Date();
1938
        final File outputFile = new File(tmpDir, "metacat.output." + d.getTime());
1939
        FileOutputStream dataSink = new FileOutputStream(outputFile);
1940
1941
        handler.readFromMetacat(metacatUrl, null,
1942
                dataSink, localId, "xml",
1943
                username,
1944
                groups, true, params);
1945
1946
        //set a timer to clean up the temp files
1947
        Timer t = new Timer();
1948
        TimerTask tt = new TimerTask() {
1949
            @Override
1950
            public void run()
1951
            {
1952
                outputFile.delete();
1953
            }
1954
        };
1955
        t.schedule(tt, 20000); //schedule after 20 secs
1956
1957
        InputStream objectStream = new FileInputStream(outputFile);
1958
        return objectStream;
1959
    }
1960
1961
    /**
1962 5621 berkley
     * return an MD5 checksum for the stream
1963
     * @param is
1964
     * @return
1965 5920 jones
     * @throws IOException
1966
     * @throws NoSuchAlgorithmException
1967 5378 berkley
     */
1968 5920 jones
    public static String checksum(InputStream is) throws NoSuchAlgorithmException, IOException
1969 5621 berkley
    {
1970
        return checksum(is, "MD5");
1971
    }
1972
1973
    /**
1974
     * produce a checksum for item using the given algorithm
1975 5920 jones
     * @throws IOException
1976
     * @throws NoSuchAlgorithmException
1977 5621 berkley
     */
1978 5920 jones
    public static String checksum(InputStream is, String algorithm) throws NoSuchAlgorithmException, IOException
1979 5378 berkley
    {
1980 5851 berkley
        return ServiceTypeUtil.checksum(is, ChecksumAlgorithm.convert(algorithm)).getValue();
1981 5378 berkley
    }
1982
1983
    /**
1984
     * parse the metacat date which looks like 2010-06-08 (YYYY-MM-DD) into
1985
     * a proper date object
1986
     * @param date
1987
     * @return
1988
     */
1989
    private Date parseMetacatDate(String date)
1990
    {
1991
        String year = date.substring(0, 4);
1992
        String month = date.substring(5, 7);
1993
        String day = date.substring(8, 10);
1994 5420 berkley
        Calendar c = Calendar.getInstance(TimeZone.getDefault());
1995 5378 berkley
        c.set(new Integer(year).intValue(),
1996
              new Integer(month).intValue(),
1997
              new Integer(day).intValue());
1998 5953 cjones
        logCrud.debug("time in parseMetacatDate: " + c.getTime());
1999 5378 berkley
        return c.getTime();
2000
    }
2001
2002
    /**
2003
     * find the size (in bytes) of a stream
2004
     * @param is
2005
     * @return
2006
     * @throws IOException
2007
     */
2008
    private long sizeOfStream(InputStream is)
2009
        throws IOException
2010
    {
2011
        long size = 0;
2012
        byte[] b = new byte[1024];
2013
        int numread = is.read(b, 0, 1024);
2014
        while(numread != -1)
2015
        {
2016
            size += numread;
2017
            numread = is.read(b, 0, 1024);
2018
        }
2019
        return size;
2020
    }
2021 5379 berkley
2022
    /**
2023
     * create system metadata with a specified id, doc and format
2024 5920 jones
     * @throws McdbDocNotFoundException
2025
     * @throws SQLException
2026
     * @throws AccessionNumberException
2027
     * @throws NumberFormatException
2028
     * @throws IOException
2029
     * @throws NoSuchAlgorithmException
2030
     * @throws PropertyNotFoundException
2031 6068 rnahf
     * @throws NotImplemented
2032
     * @throws NotFound
2033
     * @throws NotAuthorized
2034
     * @throws InvalidToken
2035
     * @throws InvalidRequest
2036
     * @throws NoSuchAlgorithmException
2037 5379 berkley
     */
2038 5920 jones
    private SystemMetadata createSystemMetadata(String localId, AuthToken token)
2039 6068 rnahf
    throws McdbDocNotFoundException, PropertyNotFoundException, AccessionNumberException, SQLException,
2040
    ServiceFailure, InvalidToken, NotAuthorized, NotFound, NotImplemented, InvalidRequest,
2041
    IOException, NoSuchAlgorithmException
2042
    {
2043
    	logCrud.debug("CrudService.createSystemMetadata() called.");
2044 5920 jones
2045 6068 rnahf
    	IdentifierManager im = IdentifierManager.getInstance();
2046
    	Hashtable<String, Object> docInfo = im.getDocumentInfo(localId);
2047 5920 jones
2048 6068 rnahf
    	//get the document text
2049
    	int rev = im.getLatestRevForLocalId(localId);
2050
    	Identifier identifier = new Identifier();
2051
    	try {
2052
    		identifier.setValue(im.getGUID(localId, rev));
2053 5920 jones
2054 6068 rnahf
    	} catch (McdbDocNotFoundException mcdbe) {
2055
    		//we're creating a new SM doc for a doc that is not in the identifier table
2056
    		//so we need to add it to
2057
    		logCrud.debug("No guid in the identifier table.  adding it for " + localId);
2058
    		im.createMapping(localId, localId);
2059
    		logCrud.debug("Mapping created for " + localId);
2060
    		AccessionNumber accNum = new AccessionNumber(localId, "NONE");
2061
    		identifier.setValue(im.getGUID(accNum.getDocid(), rev));
2062
    	}
2063 5920 jones
2064 6068 rnahf
    	logCrud.debug("Creating system metadata for guid " + identifier.getValue());
2065
    	InputStream is = this.get(token, identifier);
2066
    	SystemMetadata sm = new SystemMetadata();
2067 5920 jones
2068 6068 rnahf
    	//set the id
2069
    	sm.setIdentifier(identifier);
2070
2071
    	//set the default object format
2072
    	String doctype = (String) docInfo.get("doctype");
2073 6088 cjones
    	ObjectFormat format = ObjectFormatService.getFormat(doctype);
2074 6068 rnahf
    	if (format == null) {
2075
    		if (doctype.trim().equals("BIN")) {
2076 6088 cjones
    			format = ObjectFormatService.getFormat("application/octet-stream");
2077 6068 rnahf
    		} else {
2078 6088 cjones
    			format = ObjectFormatService.getFormat("text/plain");
2079 6068 rnahf
    		}
2080
    	}
2081
    	sm.setObjectFormat(format);
2082
    	logCrud.debug("The ObjectFormat for " + localId + " is " + format.toString());
2083
2084
    	// further parse EML documents to get data object format,
2085
    	// describes and describedBy information
2086 6088 cjones
    	if ( format == ObjectFormatService.getFormat("eml://ecoinformatics.org/eml/2.0.0") ||
2087
    			format == ObjectFormatService.getFormat("eml://ecoinformatics.org/eml/2.0.1") ||
2088
    			format == ObjectFormatService.getFormat("eml://ecoinformatics.org/eml/2.1.0") ) {
2089 6068 rnahf
2090
    		try {
2091
    			DataoneEMLParser emlParser = DataoneEMLParser.getInstance();
2092
    			EMLDocument emlDocument = emlParser.parseDocument(is);
2093
2094
    			// iterate through the data objects in the EML doc and add sysmeta
2095
    			logCrud.debug("The number of data entities is: " +
2096
    					emlDocument.distributionMetadata.size());
2097
2098
    			for( int j = 0; j < emlDocument.distributionMetadata.size(); j++ ) {
2099
2100
    				DistributionMetadata distMetadata =
2101
    					emlDocument.distributionMetadata.elementAt(j);
2102
    				String dataDocUrl = distMetadata.url;
2103
    				String dataDocMimeType = distMetadata.mimeType;
2104
    				String dataDocLocalId = "";
2105
    				logCrud.debug("\tData local ID: " + dataDocLocalId);
2106
    				logCrud.debug("\tData URL: " + dataDocUrl);
2107
    				logCrud.debug("\tData mime: " + dataDocMimeType);
2108
2109
    				//we only handle ecogrid urls right now
2110
    				if ( dataDocUrl.trim().startsWith("ecogrid://knb/") ) {
2111
    					dataDocLocalId =
2112
    						dataDocUrl.substring(dataDocUrl.indexOf("ecogrid://knb/") +
2113
    								"ecogrid://knb/".length(), dataDocUrl.length());
2114
2115
    					//set the id
2116
    					Identifier dataDocId = new Identifier();
2117
    					dataDocId.setValue(dataDocLocalId);
2118
2119
    					// add describes into EML system metadata
2120
    					sm.addDescribe(dataDocId);
2121
2122
    					SystemMetadata dataSysMeta = new SystemMetadata();
2123
    					// check if data system metadata exists
2124
    					try {
2125
    						logCrud.debug("Checking for existing system metadata for " + dataDocId.getValue());
2126
    						dataSysMeta = this.getSystemMetadata(token, dataDocId);
2127
    						// add describedBy sysmeta
2128
    						logCrud.debug("Setting describedBy for " + dataDocId.getValue() +
2129
    								" to " + identifier.getValue());
2130
    						dataSysMeta.addDescribedBy(identifier);
2131 6088 cjones
    						dataSysMeta.setObjectFormat(ObjectFormatService.getFormat(dataDocMimeType));
2132 6068 rnahf
    						this.updateSystemMetadata(dataSysMeta, getSessionData(token));
2133
2134
    					} catch ( NotFound nf ) {
2135
    						// System metadata for data doesn't exist
2136
    						logCrud.debug("There was not an existing system metadata " + "document for " + dataDocId.getValue());
2137
    						logCrud.debug("Creating a system metadata " + "document for " + dataDocId.getValue());
2138
    						dataSysMeta = this.createSystemMetadata(dataDocLocalId, token);
2139
2140
    						logCrud.debug("Setting describedBy for " + dataDocId.getValue() + " to " + identifier.getValue());
2141
    						dataSysMeta.addDescribedBy(identifier);
2142
2143
    						logCrud.debug("Setting mimeType for " + dataDocId.getValue() + " to " + dataDocMimeType);
2144 6088 cjones
    						dataSysMeta.setObjectFormat(ObjectFormatService.getFormat(dataDocMimeType));
2145 6068 rnahf
2146
    						logCrud.debug("Updating system metadata for " + dataDocId.getValue() + " to " + dataDocMimeType);
2147
    						this.updateSystemMetadata(dataSysMeta, getSessionData(token));
2148
    					}
2149
    				} // end if()
2150
    			} // end for()
2151
2152
    		} catch ( ParserConfigurationException pce ) {
2153
    			logCrud.debug("There was a problem parsing the EML document. " +
2154
    					"The error message was: " + pce.getMessage());
2155
2156
    		} catch ( SAXException saxe ) {
2157
    			logCrud.debug("There was a problem traversing the EML document. " +
2158
    					"The error message was: " + saxe.getMessage());
2159
2160
    		} catch ( XPathExpressionException xpee ) {
2161
    			logCrud.debug("There was a problem searching the EML document. " +
2162
    					"The error message was: " + xpee.getMessage());
2163
    		} // end try
2164
2165
    	} // end if()
2166
2167
    	//create the checksum
2168
    	is = this.get(token, identifier);
2169
    	String checksumS = checksum(is);
2170
    	ChecksumAlgorithm ca = ChecksumAlgorithm.convert("MD5");
2171
    	Checksum checksum = new Checksum();
2172
    	checksum.setValue(checksumS);
2173
    	checksum.setAlgorithm(ca);
2174
    	sm.setChecksum(checksum);
2175
2176
    	//set the size
2177
    	is = this.get(token, identifier);
2178
    	sm.setSize(sizeOfStream(is));
2179
2180
    	//submitter
2181
    	Principal p = new Principal();
2182
    	p.setValue((String) docInfo.get("user_owner"));
2183
    	sm.setSubmitter(p);
2184
    	sm.setRightsHolder(p);
2185
    	try {
2186
    		Date dateCreated = parseMetacatDate((String) docInfo.get("date_created"));
2187
    		sm.setDateUploaded(dateCreated);
2188
    		Date dateUpdated = parseMetacatDate((String) docInfo.get("date_updated"));
2189
    		sm.setDateSysMetadataModified(dateUpdated);
2190
    	} catch (Exception e) {
2191
    		logCrud.debug("POSSIBLE ERROR: couldn't parse a date: " + e.getMessage());
2192
    		Date dateCreated = new Date();
2193
    		sm.setDateUploaded(dateCreated);
2194
    		Date dateUpdated = new Date();
2195
    		sm.setDateSysMetadataModified(dateUpdated);
2196
    	}
2197
    	NodeReference nr = new NodeReference();
2198
    	nr.setValue(PropertyService.getProperty("dataone.memberNodeId"));
2199
    	sm.setOriginMemberNode(nr);
2200
    	sm.setAuthoritativeMemberNode(nr);
2201
2202
    	// TODO: Need to set describes/describedBy
2203
2204
    	return sm;
2205 5379 berkley
    }
2206 5870 berkley
2207
    /**
2208
     * create the listObjects pathQuery document
2209
     */
2210 5921 jones
//    private String createListObjectsPathQueryDocument()
2211
//        throws PropertyNotFoundException
2212
//    {
2213
//        String s = "<pathquery>";
2214
//        s += "<returndoctype>" + PropertyService.getProperty("crudService.listObjects.ReturnDoctype") + "</returndoctype>";
2215
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.1") + "</returnfield>";
2216
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.2") + "</returnfield>";
2217
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.3") + "</returnfield>";
2218
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.4") + "</returnfield>";
2219
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.5") + "</returnfield>";
2220
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.6") + "</returnfield>";
2221
//        s += "<returnfield>" + PropertyService.getProperty("crudService.listObjects.ReturnField.7") + "</returnfield>";
2222
//        s += "<querygroup operator=\"UNION\"><queryterm casesensitive=\"false\" searchmode=\"contains\">";
2223
//        s += "<value>%</value>";
2224
//        s += "<pathexpr>" + PropertyService.getProperty("crudService.listObjects.ReturnField.3") + "</pathexpr>";
2225
//        s += "</queryterm></querygroup></pathquery>";
2226
//
2227
//        return s;
2228
//    }
2229 5298 jones
}