Project

General

Profile

« Previous | Next » 

Revision 6362

remove CrudService -- replaced by MNodeService and CNodeService

View differences:

test/edu/ucsb/nceas/metacat/dataone/CrudServiceTest.java
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2010 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *  Purpose: To test the Access Controls in metacat by JUnit
6
 *
7
 *   '$Author: berkley $'
8
 *     '$Date: 2010-05-03 14:26:08 -0700 (Fri, 14 Aug 2009) $'
9
 * '$Revision: 5027 $'
10
 *
11
 * This program is free software; you can redistribute it and/or modify
12
 * it under the terms of the GNU General Public License as published by
13
 * the Free Software Foundation; either version 2 of the License, or
14
 * (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU General Public License
22
 * along with this program; if not, write to the Free Software
23
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
 */
25

  
26
package edu.ucsb.nceas.metacat.dataone;
27

  
28
import java.io.InputStream;
29
import java.io.StringBufferInputStream;
30
import java.security.MessageDigest;
31
import java.util.Date;
32

  
33
import junit.framework.Test;
34
import junit.framework.TestSuite;
35

  
36
import org.apache.commons.io.IOUtils;
37
import org.dataone.client.ObjectFormatCache;
38
import org.dataone.service.exceptions.BaseException;
39
import org.dataone.service.types.AuthToken;
40
import org.dataone.service.types.Checksum;
41
import org.dataone.service.types.ChecksumAlgorithm;
42
import org.dataone.service.types.DescribeResponse;
43
import org.dataone.service.types.Identifier;
44
import org.dataone.service.types.Log;
45
import org.dataone.service.types.LogEntry;
46
import org.dataone.service.types.NodeReference;
47
import org.dataone.service.types.ObjectFormat;
48
import org.dataone.service.types.ObjectInfo;
49
import org.dataone.service.types.ObjectList;
50
import org.dataone.service.types.Subject;
51
import org.dataone.service.types.SystemMetadata;
52

  
53
import edu.ucsb.nceas.MCTestCase;
54
import edu.ucsb.nceas.metacat.MetaCatServlet;
55
import edu.ucsb.nceas.metacat.client.rest.MetacatRestClient;
56
import edu.ucsb.nceas.metacat.properties.PropertyService;
57
import edu.ucsb.nceas.metacat.service.SessionService;
58
import edu.ucsb.nceas.metacat.util.SessionData;
59

  
60
/**
61
 * A JUnit test for testing the dataone CrudService class
62
 */
63
public class CrudServiceTest extends MCTestCase 
64
{   
65
    private int createCount = 0;
66
    
67
    /**
68
    * consstructor for the test
69
    */
70
    public CrudServiceTest(String name)
71
    {
72
        super(name);
73
    }
74
  
75
    /**
76
	 * Establish a testing framework by initializing appropriate objects
77
	 */
78
	public void setUp() throws Exception 
79
	{
80
		super.setUp();
81
	}
82

  
83
	/**
84
	 * Release any objects after tests are complete
85
	 */
86
	public void tearDown() 
87
	{
88
	    System.out.println(createCount + " docs created in this test session.");
89
	}
90

  
91
	/**
92
	 * Create a suite of tests to be run together
93
	 */
94
	public static Test suite() 
95
	{
96
		TestSuite suite = new TestSuite();
97
		suite.addTest(new CrudServiceTest("initialize"));
98
		
99
		suite.addTest(new CrudServiceTest("testSingletonAccessor"));
100
		suite.addTest(new CrudServiceTest("testCreateAndGet"));
101
		suite.addTest(new CrudServiceTest("testGetSystemMetadata"));
102
		suite.addTest(new CrudServiceTest("testUpdate"));
103
		suite.addTest(new CrudServiceTest("testListObjects"));
104
		suite.addTest(new CrudServiceTest("testAccessControl"));
105
		suite.addTest(new CrudServiceTest("testGetLogRecords"));
106
		suite.addTest(new CrudServiceTest("testChecksumError"));
107
		suite.addTest(new CrudServiceTest("testPublicAccess"));
108
		suite.addTest(new CrudServiceTest("testFailedCreate"));
109
		suite.addTest(new CrudServiceTest("testChecksum"));
110
		suite.addTest(new CrudServiceTest("testDescribe"));
111
		suite.addTest(new CrudServiceTest("testDelete"));
112
		suite.addTest(new CrudServiceTest("testSemiColonsInIdentifiers"));
113
		return suite;
114
	}
115
	
116
	/**
117
	 * test for the use of semi colons in identifiers
118
	 * in response to https://redmine.dataone.org/issues/1143
119
	 */
120
	public void testSemiColonsInIdentifiers()
121
	{
122
	    try
123
        {
124
            CrudService cs = CrudService.getInstance();
125
            AuthToken token = getToken();
126
            String testDoc = getTestDoc();
127
            
128
            Identifier id = new Identifier();
129
            id.setValue("someid;id;with;semi;colons;in;it." + new Date().getTime());
130
            String docid = generateDocumentId();
131
            
132
            //create the system metadata then run the create method
133
            StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
134
            SystemMetadata sm = createSystemMetadata(id, testDoc, 
135
                    ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0"));
136
            //create the doc
137
            Identifier rGuid = cs.create(token, id, sbis, sm);
138
            
139
            System.out.println("ID: " + rGuid.getValue());
140
            assertTrue(rGuid.toString().equals(id.toString())); 
141
            System.out.println("created doc with id " + id.getValue());
142
        }
143
        catch(Exception e)
144
        {
145
            fail("Unexpected error in testDescribe: " + e.getMessage());
146
        }
147
	}
148
	
149
	/**
150
	 * test the delete function
151
	 */
152
	public void testDelete()
153
	{
154
	    try
155
        {
156
            CrudService cs = CrudService.getInstance();
157
            AuthToken token = getToken();
158
            String doc = getTestDoc();
159
            Identifier id = createDoc(token, doc);
160
            System.out.println("ID: " + id.getValue());
161
            makeDocPublic(token, id, true);
162
            cs.get(token, id);
163
            cs.delete(token, id);
164
            //there should be a try/catch around the next statement
165
            //to make sure that the document is no longer readable,
166
            //but because the data is output in a 2nd thread, the
167
            //exception does not get caught here.  See 
168
            //https://redmine.dataone.org/issues/1079
169
            //cs.get(token, id);
170
        }
171
        catch(Exception e)
172
        {
173
            fail("Unexpected error in testDescribe: " + e.getMessage());
174
        }
175
	}
176
	
177
	/**
178
	 * test the describe crud function
179
	 */
180
	public void testDescribe()
181
	{
182
	    try
183
	    {
184
	        CrudService cs = CrudService.getInstance();
185
	        AuthToken token = getToken();
186
	        
187
	        String doc = getTestDoc();
188
	        Identifier id = createDoc(token, doc);
189
	        System.out.println("ID: " + id.getValue());
190
	        makeDocPublic(token, id, true);
191
	        
192
	        SystemMetadata sm = cs.getSystemMetadata(token, id);
193
	        
194
	        DescribeResponse dr = cs.describe(token, id);
195
	        
196
	        assertTrue(dr.getDataONE_Checksum().getValue().equals(sm.getChecksum().getValue()));
197
	        assertTrue(dr.getDataONE_ObjectFormat().toString().equals(sm.getObjectFormat().getFmtid().getValue()));
198
	        assertTrue(dr.getLast_Modified().getTime() == sm.getDateSysMetadataModified().getTime());
199
	        assertTrue(dr.getContent_Length() == sm.getSize());
200
	    }
201
	    catch(Exception e)
202
	    {
203
	        fail("Unexpected error in testDescribe: " + e.getMessage());
204
	    }
205
	}
206
	
207
	/**
208
	 * test the checksum creation
209
	 */
210
	public void testChecksum()
211
	{
212
	    try
213
	    {
214
	        CrudService cs = CrudService.getInstance();
215
	        AuthToken token = getToken();
216
	        System.out.println("token: " + token.getToken());
217
	        String doc = getTestDoc();
218
	        Identifier id = createDoc(token, doc);
219
	        System.out.println("ID: " + id.getValue());
220
            makeDocPublic(token, id, true);
221
	        String doc2 = getDoc(token, id);
222
            
223
	        String checksum = checksum(doc);
224
            Checksum checksum2 = cs.getChecksum(token, id, "MD5");
225
            System.out.println("doc: \"" + doc + "\"");
226
            System.out.println("doc2: \"" + doc2 + "\"");
227
            System.out.println("checksum1: " + checksum);
228
            System.out.println("checksum2: " + checksum2.getValue());
229
            assertTrue(checksum.equals(checksum2.getValue()));
230
            
231
	    }
232
	    catch(Exception e)
233
	    {
234
	        fail("Unexpected error in testChecksum: " + e.getMessage());
235
	    }
236
	    
237
	}
238
	
239
	/**
240
	 * insert an invalid document and make sure create fails and does not
241
	 * leave any artifacts behind
242
	 */
243
	public void testFailedCreate()
244
	{
245
	    try
246
	    {
247
	        String invalidDoc = "<xxx></yyy>";
248
	        System.out.println("trying to insert doc " + invalidDoc);
249
	        CrudService cs = CrudService.getInstance();
250
            AuthToken token = getToken();
251
            //run create
252
            try
253
            {
254
                Identifier id = createDoc(token, invalidDoc);
255
                fail("Should have thrown an exception.");
256
            }
257
            catch(Exception e)
258
            {
259
                //e.printStackTrace();
260
            }
261
            
262
	    }
263
	    catch(Exception e)
264
	    {
265
	        fail("unexpected exception in testFailedCreate: " + e.getMessage());
266
	    }
267
	}
268
	
269
	/**
270
	 * test to make sure that get and listObjects methods are publicly accessible
271
	 */
272
	public void testPublicAccess()
273
	{
274
	    try
275
	    {
276
	        System.out.println("********************* testPublicAccess *********************");
277
	        AuthToken token = new AuthToken("public");
278
	        //AuthToken token = getToken();
279
	        CrudService cs = CrudService.getInstance();
280
	        ObjectList ol = cs.listObjects(token, null, null, null);
281
	        System.out.println("ol: " + ol.sizeObjectInfoList());
282
	        assertTrue(ol.sizeObjectInfoList() > 0);
283
	        
284
	        ObjectInfo oi = ol.getObjectInfo(0);
285
	        String s = getDoc(token, oi.getIdentifier());
286
	        assertNotNull(s);
287
	        
288
	        try
289
	        { //try a create with the public auth.  should fail
290
	            Identifier id = new Identifier();
291
	            String docid = generateDocumentId();
292
	            id.setValue(docid);
293
	            String testDoc = getTestDoc();
294
	            StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
295
	            ObjectFormat of1 = ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0");
296
	            SystemMetadata sm = createSystemMetadata(id, testDoc, of1);
297
	            assertFalse(sm.getChecksum().getValue().startsWith("MD5"));
298
	            //create the doc
299
	            Identifier idC = cs.create(token, id, sbis, sm);
300
	            fail("Should have thrown an auth exception");
301
	        }
302
	        catch(Exception e)
303
	        {
304
	            
305
	        }
306
	        
307
	        //create a legit doc
308
	        token = getToken();
309
	        Identifier id = new Identifier();
310
            String docid = generateDocumentId();
311
            id.setValue(docid);
312
            String testDoc = getTestDoc();
313
            StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
314
            ObjectFormat of1 = ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0");
315
            SystemMetadata sm = createSystemMetadata(id, testDoc, of1);
316
            assertFalse(sm.getChecksum().getValue().startsWith("MD5"));
317
            //create the doc
318
            Identifier idC = cs.create(token, id, sbis, sm);
319
            //make it public, then use a public token to try to get it
320
            InputStream data = null;
321
            try
322
            {
323
                AuthToken publicToken = new AuthToken("public");
324
                data = cs.get(publicToken, id);
325
                data.read();
326
                
327
                fail("should have thrown an exception");
328
            }
329
            catch(Exception e)
330
            {
331
                /*System.out.println("%%%%%%%%%%%%%%%%%%%%%%%getting result");
332
                Object o = ((InputStreamFromOutputStream)data).getResult();
333
                System.out.println("result: " + o);
334
                System.out.println("exception thrown!");
335
                System.out.println("exception thrown: " + e.getClass().getName());*/
336
            }
337
            
338
            
339
            
340
            makeDocPublic(token, id, true);
341
            token = new AuthToken("public");
342
	        data = cs.get(token, id);
343
	    }
344
	    catch(Exception e)
345
	    {
346
	        fail("Error in testPublicAccess: " + e.getMessage());
347
	    }
348
	    
349
	}
350
	
351
	/**
352
	 * test for an error where the checksum algorithm gets appended onto the checksum.
353
	 */
354
	public void testChecksumError()
355
	{
356
	    printTestHeader("testChecksumError");
357
	    try
358
	    {
359
	        Date d1 = new Date(new Date().getTime() - 5000);
360
	        CrudService cs = CrudService.getInstance();
361
	        AuthToken token = getToken();
362
	        ObjectFormat of1 = ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0");
363
	        //create docs at different times
364

  
365
	        Identifier id = new Identifier();
366
	        String docid = "test." + new Date().getTime();
367
	        id.setValue(docid);
368

  
369
	        //create the system metadata then run the create method
370
	        String testDoc = getTestDoc();
371
	        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
372
	        SystemMetadata sm = createSystemMetadata(id, testDoc, of1);
373
	        assertFalse(sm.getChecksum().getValue().startsWith("MD5"));
374
	        //create the doc
375
	        Identifier idC = cs.create(token, id, sbis, sm);
376
	        makeDocPublic(token, id, true);
377
	        assertTrue(idC.getValue().equals(id.getValue()));
378
	        SystemMetadata smC = getSystemMetadata(token, idC);
379
	        assertFalse(smC.getChecksum().getValue().startsWith("MD5"));
380
	        
381
	        Date d2 = new Date(new Date().getTime() + 5000);
382
	        
383
	        ObjectList ol = cs.listObjects(token, d1, d2, of1);
384
	        assertTrue(ol.sizeObjectInfoList() > 0);
385
	        ObjectInfo oi = ol.getObjectInfo(0);
386
	        //this will fail if the error state exists.
387
	        assertFalse(oi.getChecksum().getValue().startsWith("MD5"));
388
	    }
389
	    catch(Exception e)
390
	    {
391
	        fail("Unexpected exception: " + e.getMessage());
392
	    }
393
        
394
	}
395
	
396
	/**
397
	 * test CrudService.getLogRecords
398
	 */
399
	public void testGetLogRecords()
400
	{
401
	    printTestHeader("testGetLogRecords");
402
	    try
403
	    {
404
	        CrudService cs = CrudService.getInstance();
405
	        AuthToken token = getToken();
406
	        Date fromDate = new Date();
407
	        Identifier id = createDoc(token, getTestDoc());
408
	        Date toDate = new Date();
409
	        Log lrs = cs.getLogRecords(token, fromDate, toDate, null);
410
	        assertNotNull(lrs);
411
	        System.out.println("log entry size: " + lrs.sizeLogEntryList());
412
	        assertTrue(lrs.sizeLogEntryList() == 1);
413
	        LogEntry lrLogEvent = lrs.getLogEntry(0);
414
	        assertTrue(lrLogEvent.getEvent().name().equals("CREATE"));
415
	        assertTrue(lrLogEvent.getIdentifier().getValue().equals(id.getValue()));
416
	    }
417
	    catch(Exception e)
418
	    {
419
	        e.printStackTrace();
420
	        fail("testGetLogRecords threw an unexpected exception: " + e.getMessage());
421
	    }
422
	}
423
	
424
	/**
425
	 * make sure that only valid sessions can update/delete
426
	 */
427
	public void testAccessControl()
428
	{
429
	    printTestHeader("testAccessControl");
430
        try
431
        {
432
            CrudService cs = CrudService.getInstance();
433
            AuthToken token = getToken();
434
            //create a doc
435
            Identifier id = createDoc(token, getTestDoc());
436
            
437
            //get the doc and sysmetadata
438
            String gotDoc = getDoc(token, id);
439
            SystemMetadata sm = getSystemMetadata(token, id);
440
            
441
            //break the session id
442
            String sessionid = "somefakesessionid";
443
            token = new AuthToken(sessionid);
444
            
445
            //update the doc
446
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
447
            Identifier newid = new Identifier();
448
            newid.setValue(generateDocumentId());
449
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
450
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
451
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
452
            fail("exception should have been thrown.");
453
        }
454
        catch(Exception e)
455
        {
456
        }
457
        
458
        try
459
        {
460
            CrudService cs = CrudService.getInstance();
461
            AuthToken token = new AuthToken("somefakesessionid");
462
            //create a doc
463
            Identifier id = createDoc(token, getTestDoc());
464
            fail("exception should have been thrown.");
465
        }
466
        catch(Exception e)
467
        {
468
        }
469
	}
470
	
471
	/**
472
	 * public ObjectList listObjects(AuthToken token, Date startTime, Date endTime, 
473
     *     ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
474
     *       throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
475
	 */
476
	public void testListObjects()
477
	{
478
	    printTestHeader("testListObjects");
479
	    try
480
	    {
481
	        CrudService cs = CrudService.getInstance();
482
	        AuthToken token = getToken();
483
	        ObjectFormat of1 = ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0");
484
	        ObjectFormat of2 = ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.0.0");
485
	        //create docs at different times
486
	        Date d1 = new Date();
487
	        Identifier id1 = createDoc(token, getTestDoc(EML2_1_0), of1);
488
            SystemMetadata sm1 = getSystemMetadata(token, id1);
489
            
490
            Date d2 = new Date();
491
            Identifier id2 = createDoc(token, getTestDoc(EML2_0_0), of2);
492
            makeDocPublic(token, id2, true);
493
            SystemMetadata sm2 = getSystemMetadata(token, id2);
494
            
495
            Date d3 = new Date();
496
            Identifier id3 = createDoc(token, getTestDoc(EML2_1_0), of1);
497
            makeDocPublic(token, id3, true);
498
            SystemMetadata sm3 = getSystemMetadata(token, id3);
499
              
500
            Date d4 = new Date();
501
            Identifier id4 = createDoc(token, getTestDoc(EML2_0_0), of2);
502
            makeDocPublic(token, id4, true);
503
            SystemMetadata sm4 = getSystemMetadata(token, id4);
504
            
505
            Date d5 = new Date();
506
            Identifier id5 = createDoc(token, getTestDoc(EML2_1_0), of1);
507
            makeDocPublic(token, id5, true);
508
            SystemMetadata sm5 = getSystemMetadata(token, id5);  
509
             
510
            Date d6 = new Date();
511
            
512
            //now get the objects for specific time ranges and test that it returns
513
            //the correct objects
514
            
515
            //ObjectList list = cs.listObjects(token, null, null, null);
516
            //System.out.println("list size: " + list.sizeObjectInfoList());
517
           
518
            //should return sm1 and sm2
519
            ObjectList list1 = cs.listObjects(token, d1, d3, null);
520
            assertTrue(list1.sizeObjectInfoList() == 2);
521
            assertTrue(idInObjectList(id1, list1));
522
            assertTrue(idInObjectList(id2, list1));
523
            
524
            ObjectInfo info = list1.getObjectInfo(0);
525
            
526
            
527
            //should only return sm1
528
            ObjectList list2 = cs.listObjects(token, d1, d3, of1);
529
            assertTrue(list2.sizeObjectInfoList() == 1);
530
            assertTrue(idInObjectList(id1, list2));
531
            
532
            //should return sm1-sm4
533
            ObjectList list3 = cs.listObjects(token, d1, d5, null);
534
            assertTrue(list3.sizeObjectInfoList() == 4);
535
            ObjectInfo oi4 = list3.getObjectInfo(0);
536
            assertTrue(idInObjectList(id1, list3));
537
            assertTrue(idInObjectList(id2, list3));
538
            assertTrue(idInObjectList(id3, list3));
539
            assertTrue(idInObjectList(id4, list3));
540
            
541
            //should only return sm2 and sm4
542
            ObjectList list4 = cs.listObjects(token, d1, d5, of2);
543
            assertTrue(list4.sizeObjectInfoList() == 2);
544
            assertTrue(idInObjectList(id2, list4));
545
            assertTrue(idInObjectList(id4, list4));
546
            
547
            //should return all
548
            ObjectList list5 = cs.listObjects(token, d1, d6, null);
549
            assertTrue(list5.sizeObjectInfoList() == 5);
550
            assertTrue(idInObjectList(id1, list5));
551
            assertTrue(idInObjectList(id2, list5));
552
            assertTrue(idInObjectList(id3, list5));
553
            assertTrue(idInObjectList(id4, list5));
554
            assertTrue(idInObjectList(id5, list5));
555
            
556
            //should return 1, 3, 5
557
            ObjectList list6 = cs.listObjects(token, d1, d6, of1);
558
            assertTrue(list6.sizeObjectInfoList() == 3);
559
            assertTrue(idInObjectList(id1, list6));
560
            assertTrue(idInObjectList(id3, list6));
561
            assertTrue(idInObjectList(id5, list6));
562
            
563
            //should return 4 (id1 is not public)
564
            token = new AuthToken("public");
565
            ObjectList list7 = cs.listObjects(token, d1, d6, null);
566
            //System.out.println("list7 size: " + list7.sizeObjectInfoList());
567
            assertTrue(list7.sizeObjectInfoList() == 5);
568
            
569
            //test paging
570
            ObjectList list8 = cs.listObjects(token, d1, d6, null, false, 2, 2);
571
            assertTrue(list8.getCount() == 2);
572
            assertTrue(list8.getStart() == 2);
573
            assertTrue(list8.getTotal() == 5);
574
            
575
            
576
	    }
577
	    catch(Exception e)
578
	    {
579
	        //e.printStackTrace();
580
	        fail("Error in listObjects: " + e.getMessage());
581
	    }
582
	}
583
	
584
	private boolean idInObjectList(Identifier id, ObjectList list)
585
	{
586
	    for(int i=0; i<list.sizeObjectInfoList(); i++)
587
	    {
588
	        ObjectInfo oi = list.getObjectInfo(i);
589
	        if(id.getValue().equals(oi.getIdentifier().getValue()))
590
	            return true;
591
	    }
592
	    return false;
593
	}
594
	
595
	/**
596
	 * public Identifier update(AuthToken token, Identifier guid, 
597
     *       InputStream object, Identifier obsoletedGuid, SystemMetadata sysmeta) 
598
     *         throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
599
     *           UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
600
     *           NotImplemented
601
	 */
602
	public void testUpdate()
603
	{
604
	    printTestHeader("testUpdate");
605
	    try
606
	    {
607
	        CrudService cs = CrudService.getInstance();
608
	        AuthToken token = getToken();
609
            //create a doc
610
            Identifier id = createDoc(token, getTestDoc());
611
            
612
            //get the doc and sysmetadata
613
            String gotDoc = getDoc(token, id);
614
            SystemMetadata sm = getSystemMetadata(token, id);
615
            
616
            //update the doc
617
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
618
            Identifier newid = new Identifier();
619
            newid.setValue(generateDocumentId());
620
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
621
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
622
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
623
            
624
            //get doc - check that it matches update
625
            String newdoc = getDoc(token, newid);
626
            assertTrue(gotDoc.equals(newdoc));
627
            
628
            //get sysmeta - check that ids and other fields are updated
629
            SystemMetadata newnewsm = getSystemMetadata(token, id);
630
            assertTrue(newnewsm.getObsoletedBy(0).getValue().equals(newid.getValue()));
631
            
632
            //get the new sysmeta and make sure the obsoletes field is set
633
            SystemMetadata newnewnewsm = getSystemMetadata(token, newid);
634
            assertTrue(newnewnewsm.getObsolete(0).getValue().equals(id.getValue()));
635
        }
636
        catch(Exception e)
637
        {
638
            e.printStackTrace();
639
            fail("Error in testUpdate: " + e.getMessage());
640
        }
641
	}
642
	
643
	/**
644
	 * public SystemMetadata getSystemMetadata(AuthToken token, Identifier guid)
645
     *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
646
     *       InvalidRequest, NotImplemented
647
	 */
648
	public void testGetSystemMetadata()
649
	{
650
	    printTestHeader("testGetSystemMetadata");
651
	    try
652
	    {
653
            CrudService cs = CrudService.getInstance();
654
            AuthToken token = getToken();
655
            //run create
656
            Identifier id = createDoc(token, getTestDoc());
657
            //get the systemMetadata and make sure it is the correct object for this testDoc
658
            SystemMetadata sm = getSystemMetadata(token, id);
659
            assertTrue(sm.getIdentifier().getValue().equals(id.getValue()));
660
            assertTrue(sm.getChecksum().getValue().equals(checksum(getTestDoc())));
661
            
662
            try
663
            {
664
                Identifier fakeid = new Identifier();
665
                fakeid.setValue("somethingfake.234234");
666
                getSystemMetadata(token, fakeid);
667
                fail("getSystemMetadata should have thrown an exception.");
668
            }
669
            catch(Exception e)
670
            {
671
                assertTrue(true);
672
            }
673
        }
674
        catch(Exception e)
675
        {
676
            e.printStackTrace();
677
            fail("Error testing system metadata: " + e.getMessage());
678
        }
679
	}
680
	
681
	/**
682
	 * create(AuthToken token, Identifier guid, InputStream object, SystemMetadata sysmeta) 
683
   *   throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
684
   *       InsufficientResources, InvalidSystemMetadata, NotImplemented
685
   *
686
   * public InputStream get(AuthToken token, Identifier guid)
687
   *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
688
   *       NotImplemented
689
	 */
690
	public void testCreateAndGet()
691
	{
692
	    printTestHeader("testCreateAndGet");
693
	    try
694
	    {
695
	        CrudService cs = CrudService.getInstance();
696
	        AuthToken token = getToken();
697
	        //run create
698
	        Identifier id = createDoc(token, getTestDoc());
699
	        //make these docs public for debugging purposes.
700
	        makeDocPublic(token, id, true);
701
            //compare the docs
702
            String gotDoc = getDoc(token, id);
703
            assertTrue(gotDoc.trim().equals(getTestDoc().trim()));
704
            
705
            try
706
            {
707
                Identifier fakeid = new Identifier();
708
                fakeid.setValue("somethingfake.234234");
709
                getDoc(token, fakeid);
710
                fail("testCreateAndGet should have thrown an exception.");
711
            }
712
            catch(Exception e)
713
            {
714
                assertTrue(true);
715
            }
716
        }
717
        catch(Exception e)
718
        {
719
            e.printStackTrace();
720
            fail("Error in testCreate: " + e.getMessage());
721
        }
722
	}
723
	
724
	/**
725
	 * getInstance()
726
	 */
727
	public void testSingletonAccessor()
728
	{
729
	    printTestHeader("testSingletonAccessor");
730
	    CrudService cs = CrudService.getInstance();
731
	    assertNotNull(cs);
732
	}
733
	
734
	/**
735
	 * Run an initial test that always passes to check that the test harness is
736
	 * working.
737
	 */
738
	public void initialize() 
739
	{
740
	    printTestHeader("initialize");
741
		assertTrue(1 == 1);
742
	}
743
	
744
	/**
745
	 * return the systemMetadata object for id
746
	 */
747
	private SystemMetadata getSystemMetadata(AuthToken token, Identifier id)
748
	  throws BaseException
749
	{
750
	    CrudService cs = CrudService.getInstance();
751
	    return cs.getSystemMetadata(token, id);
752
	}
753
	
754
	/**
755
	 * get a doc from metacat using CrudService.get()
756
	 */
757
	private String getDoc(AuthToken token, Identifier id)
758
	  throws Exception
759
	{
760
	    CrudService cs = CrudService.getInstance();
761
        InputStream gotDocStream = cs.get(token, id);
762
        return IOUtils.toString(gotDocStream);
763
	}
764
	
765
	public String getTestDoc()
766
	{
767
	    return getTestDoc("eml://ecoinformatics.org/eml-2.1.0");
768
	}
769
	
770
	/**
771
	 * return a test document.  objectFormat should come from MCTestCase
772
	 */
773
	public String getTestDoc(String objectFormat)
774
	{
775
	    if(objectFormat == null)
776
	    {
777
	        return "<?xml version=\"1.0\"?><test><somecontent>This is some content XXX</somecontent></test>\n";
778
	    }
779
	    
780
	    String accessBlock = getAccessBlock("public", true, true,
781
                false, false, false);
782
	    
783
	    
784
	    return getTestEmlDoc("Test identifier manager", objectFormat, null,
785
	                null, "http://fake.example.com/somedata", null,
786
	                accessBlock, null, null,
787
	                null, null);
788
	}
789
	
790
	/**
791
	 * authenticate and return a token
792
	 * use the test.mcUser and test.mcPassword username/password combo
793
	 */
794
	public AuthToken getToken()
795
	  throws Exception
796
	{
797
        String username = PropertyService.getProperty("test.mcUser");
798
        String password = PropertyService.getProperty("test.mcPassword");
799
        return getToken(username, password);
800
	}
801
	
802
	/**
803
	 * authenticate and return a token using the given credentials
804
	 */
805
	public AuthToken getToken(String username, String password)
806
	  throws Exception
807
	{
808
	    CrudService cs = CrudService.getInstance();
809
        //login and get a sessionid
810
        MetacatRestClient restClient = new MetacatRestClient(cs.getContextUrl());
811
        String response = restClient.login(username, password);
812
        String sessionid = restClient.getSessionId();
813
        SessionService sessionService = SessionService.getInstance();
814
        sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
815
        AuthToken token = new AuthToken(sessionid);
816
        return token;
817
	}
818
	
819
	/**
820
	 * create a doc using CrudService.create() and return its id
821
	 */
822
	public Identifier createDoc(AuthToken token, String testDoc) throws Exception
823
	{
824
	    return createDoc(token, testDoc, ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0"));
825
	}
826
	
827
	/**
828
	 * create a doc using CrudService.create() and return its id
829
	 */
830
	public Identifier createDoc(AuthToken token, String testDoc, ObjectFormat format) throws Exception
831
	{
832
	    Identifier id;
833
        CrudService cs = CrudService.getInstance();
834
        
835
        id = new Identifier();
836
        String docid = generateDocumentId();
837
        id.setValue(docid);
838
        
839
        //create the system metadata then run the create method
840
        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
841
        SystemMetadata sm = createSystemMetadata(id, testDoc, format);
842
        //create the doc
843
        cs.create(token, id, sbis, sm);
844
        createCount++;
845
        return id;
846
	}
847
	
848
	/**
849
	 * create a generic SystemMetadata object for testing
850
	 */
851
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc)
852
	  throws Exception
853
	{
854
	    return createSystemMetadata(id, testDoc, 
855
	            ObjectFormatCache.getInstance().getFormat("eml://ecoinformatics.org/eml-2.1.0"));
856
	}
857
	
858
	/**
859
	 * create system metadata with a specified id, doc and format
860
	 */
861
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc, ObjectFormat format)
862
	  throws Exception
863
	{
864
	    SystemMetadata sm = new SystemMetadata();
865
        //set the id
866
        sm.setIdentifier(id);
867
        sm.setObjectFormat(format);
868
        //create the checksum
869
        String checksumS = checksum(testDoc);
870
        ChecksumAlgorithm ca = ChecksumAlgorithm.convert("MD5");
871
        Checksum checksum = new Checksum();
872
        checksum.setValue(checksumS);
873
        checksum.setAlgorithm(ca);
874
        sm.setChecksum(checksum);
875
        //set the size
876
        sm.setSize(testDoc.getBytes(MetaCatServlet.DEFAULT_ENCODING).length);
877
        //submitter
878
        Subject p = new Subject();
879
        p.setValue("joe");
880
        sm.setSubmitter(p);
881
        sm.setRightsHolder(p);
882
        sm.setDateUploaded(new Date());
883
        sm.setDateSysMetadataModified(new Date());
884
        NodeReference nr = new NodeReference();
885
        nr.setValue("metacat");
886
        sm.setOriginMemberNode(nr);
887
        sm.setAuthoritativeMemberNode(nr);
888
        return sm;
889
	}
890
	
891
	/**
892
	 *  make a document public in metacat by inserting an access document
893
	 * @param id
894
	 */
895
	private void makeDocPublic(AuthToken token, Identifier id, boolean systemMetadataToo)
896
	  throws Exception
897
	{
898
	    CrudService cs = CrudService.getInstance();
899
	    cs.setAccess(token, id, "public", "read", "allow", "allowFirst", systemMetadataToo);
900
	}
901
	
902
	/**
903
	 * print a header to start each test
904
	 */
905
	private void printTestHeader(String testName)
906
	{
907
	    System.out.println();
908
	    System.out.println("*************** " + testName + " ***************");
909
	}
910
  
911
	/**
912
	 * produce an md5 checksum for item
913
	 */
914
	private String checksum(String item)
915
	  throws Exception
916
	{
917
        StringBufferInputStream fis =  new StringBufferInputStream(item);
918
        
919
        byte[] buffer = new byte[1024];
920
        MessageDigest complete = MessageDigest.getInstance("MD5");
921
        int numRead;
922
        
923
        do 
924
        {
925
          numRead = fis.read(buffer);
926
          if (numRead > 0) 
927
          {
928
            complete.update(buffer, 0, numRead);
929
          }
930
        } while (numRead != -1);
931
        
932
        
933
        return getHex(complete.digest());
934
	}
935
	
936
	/**
937
	 * convert a byte array to a hex string
938
	 */
939
	private static String getHex( byte [] raw ) 
940
	{
941
	    final String HEXES = "0123456789ABCDEF";
942
        if ( raw == null ) {
943
          return null;
944
        }
945
        final StringBuilder hex = new StringBuilder( 2 * raw.length );
946
        for ( final byte b : raw ) {
947
          hex.append(HEXES.charAt((b & 0xF0) >> 4))
948
             .append(HEXES.charAt((b & 0x0F)));
949
        }
950
        return hex.toString();
951
  }
952
}
src/edu/ucsb/nceas/metacat/dataone/CrudService.java
1
/**
2
 *  '$RCSfile$'
3
 *  Copyright: 2000 Regents of the University of California and the
4
 *              National Center for Ecological Analysis and Synthesis
5
 *
6
 *   '$Author: $'
7
 *     '$Date: 2009-06-13 15:28:13 +0300  $'
8
 *
9
 * This program is free software; you can redistribute it and/or modify
10
 * it under the terms of the GNU General Public License as published by
11
 * the Free Software Foundation; either version 2 of the License, or
12
 * (at your option) any later version.
13
 *
14
 * This program is distributed in the hope that it will be useful,
15
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
 * GNU General Public License for more details.
18
 *
19
 * You should have received a copy of the GNU General Public License
20
 * along with this program; if not, write to the Free Software
21
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22
 */
23
package edu.ucsb.nceas.metacat.dataone;
24

  
25
import java.io.ByteArrayInputStream;
26
import java.io.File;
27
import java.io.FileInputStream;
28
import java.io.FileNotFoundException;
29
import java.io.FileOutputStream;
30
import java.io.IOException;
31
import java.io.InputStream;
32
import java.io.OutputStream;
33
import java.security.NoSuchAlgorithmException;
34
import java.sql.SQLException;
35
import java.text.DateFormat;
36
import java.util.Calendar;
37
import java.util.Date;
38
import java.util.Enumeration;
39
import java.util.Hashtable;
40
import java.util.List;
41
import java.util.TimeZone;
42
import java.util.Timer;
43
import java.util.TimerTask;
44
import java.util.Vector;
45

  
46
import javax.servlet.http.HttpServletRequest;
47

  
48
import org.apache.commons.io.IOUtils;
49
import org.apache.log4j.Logger;
50
import org.dataone.service.exceptions.IdentifierNotUnique;
51
import org.dataone.service.exceptions.InsufficientResources;
52
import org.dataone.service.exceptions.InvalidRequest;
53
import org.dataone.service.exceptions.InvalidSystemMetadata;
54
import org.dataone.service.exceptions.InvalidToken;
55
import org.dataone.service.exceptions.NotAuthorized;
56
import org.dataone.service.exceptions.NotFound;
57
import org.dataone.service.exceptions.NotImplemented;
58
import org.dataone.service.exceptions.ServiceFailure;
59
import org.dataone.service.exceptions.UnsupportedType;
60
import org.dataone.service.mn.MemberNodeCrud;
61
import org.dataone.service.types.AuthToken;
62
import org.dataone.service.types.Checksum;
63
import org.dataone.service.types.ChecksumAlgorithm;
64
import org.dataone.service.types.DescribeResponse;
65
import org.dataone.service.types.Event;
66
import org.dataone.service.types.Identifier;
67
import org.dataone.service.types.Log;
68
import org.dataone.service.types.LogEntry;
69
import org.dataone.service.types.NodeReference;
70
import org.dataone.service.types.ObjectFormat;
71
import org.dataone.service.types.ObjectList;
72
import org.dataone.service.types.Subject;
73
import org.dataone.service.types.SystemMetadata;
74
import org.dataone.service.types.util.ServiceTypeUtil;
75

  
76
import edu.ucsb.nceas.metacat.AccessionNumberException;
77
import edu.ucsb.nceas.metacat.DocumentImpl;
78
import edu.ucsb.nceas.metacat.EventLog;
79
import edu.ucsb.nceas.metacat.IdentifierManager;
80
import edu.ucsb.nceas.metacat.McdbDocNotFoundException;
81
import edu.ucsb.nceas.metacat.McdbException;
82
import edu.ucsb.nceas.metacat.MetacatHandler;
83
import edu.ucsb.nceas.metacat.client.InsufficientKarmaException;
84
import edu.ucsb.nceas.metacat.client.rest.MetacatRestClient;
85
import edu.ucsb.nceas.metacat.properties.PropertyService;
86
import edu.ucsb.nceas.metacat.replication.ForceReplicationHandler;
87
import edu.ucsb.nceas.metacat.service.SessionService;
88
import edu.ucsb.nceas.metacat.util.DocumentUtil;
89
import edu.ucsb.nceas.metacat.util.SessionData;
90
import edu.ucsb.nceas.utilities.ParseLSIDException;
91
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
92

  
93
/**
94
 * 
95
 * Implements DataONE MemberNode CRUD API for Metacat. 
96
 * 
97
 * @author Matthew Jones
98
 */
99
public class CrudService implements MemberNodeCrud
100
{
101
    private static CrudService crudService = null;
102

  
103
    private MetacatHandler handler;
104
    private Hashtable<String, String[]> params;
105
    private Logger logMetacat = null;
106
    private Logger logCrud = null;
107
    
108
    private String metacatUrl;
109
    
110
    /**
111
     * singleton accessor
112
     */
113
    public static CrudService getInstance() 
114
    {
115
      if(crudService == null)
116
      {
117
        crudService = new CrudService();
118
      }
119
      
120
      return crudService;
121
    }
122
    
123
    /**
124
     * Constructor, private for singleton access
125
     */
126
    private CrudService() {
127
        logMetacat = Logger.getLogger(CrudService.class);
128
        logCrud = Logger.getLogger("DataOneLogger");
129
        try
130
        {
131
            String server = PropertyService.getProperty("server.name");
132
            String port = PropertyService.getProperty("server.httpPort");
133
            String context = PropertyService.getProperty("application.context");
134
            metacatUrl = "http://" + server + ":" + port + "/" + context + "/d1";
135
            logMetacat.debug("Initializing CrudService with url " + metacatUrl);
136
        }
137
        catch(Exception e)
138
        {
139
            logMetacat.error("Could not find servlet url in CrudService: " + e.getMessage());
140
            e.printStackTrace();
141
            throw new RuntimeException("Error getting servlet url in CrudService: " + e.getMessage());
142
        }
143
        
144
        params = new Hashtable<String, String[]>();
145
        handler = new MetacatHandler(new Timer());
146
    }
147
    
148
    /**
149
     * return the context url CrudService is using.
150
     */
151
    public String getContextUrl()
152
    {
153
        return metacatUrl;
154
    }
155
    
156
    /**
157
     * Set the context url that this service uses.  It is normally not necessary
158
     * to call this method unless you are trying to connect to a server other
159
     * than the one in which this service is installed.  Otherwise, this value is
160
     * taken from the metacat.properties file (server.name, server.port, application.context).
161
     */
162
    public void setContextUrl(String url)
163
    {
164
        metacatUrl = url;
165
    }
166
    
167
    /**
168
     * set the params for this service from an HttpServletRequest param list
169
     */
170
    public void setParamsFromRequest(HttpServletRequest request)
171
    {
172
        @SuppressWarnings("unchecked")
173
        Enumeration<String> paramlist = request.getParameterNames();
174
        while (paramlist.hasMoreElements()) {
175
            String name = (String) paramlist.nextElement();
176
            String[] value = (String[])request.getParameterValues(name);
177
            params.put(name, value);
178
        }
179
    }
180
    
181
    /**
182
     * Authenticate against metacat and get a token.
183
     * @param username
184
     * @param password
185
     * @return
186
     * @throws ServiceFailure
187
     */
188
    public AuthToken authenticate(String username, String password)
189
      throws ServiceFailure
190
    {
191
        /* TODO:
192
         * This method is not in the original D1 crud spec.  It is highly
193
         * metacat centric.  Higher level decisions need to be made on authentication
194
         * interfaces for D1 nodes.
195
         */
196
        try
197
        {
198
            MetacatRestClient restClient = new MetacatRestClient(getContextUrl());   
199
            String response = restClient.login(username, password);
200
            String sessionid = restClient.getSessionId();
201
            SessionService sessionService = SessionService.getInstance();
202
            sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
203
            AuthToken token = new AuthToken(sessionid);
204
            EventLog.getInstance().log(metacatUrl,
205
                    username, null, "authenticate");
206
            logCrud.info("authenticate");
207
            return token;
208
        }
209
        catch(Exception e)
210
        {
211
            throw new ServiceFailure("1620", "Error authenticating with metacat: " + e.getMessage());
212
        }
213
    }
214
    
215
    /**
216
     * set the parameter values needed for this request
217
     */
218
    public void setParameter(String name, String[] value)
219
    {
220
        params.put(name, value);
221
    }
222
    
223

  
224
    
225
    
226
    
227
    /**
228
     * create an object via the crud interface
229
     */
230
    public Identifier create(AuthToken token, Identifier guid, 
231
            InputStream object, SystemMetadata sysmeta) throws InvalidToken, 
232
            ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
233
            InsufficientResources, InvalidSystemMetadata, NotImplemented {
234
        logMetacat.debug("Starting CrudService.create()...");
235
        
236
        // authenticate & get user info
237
        SessionData sessionData = getSessionData(token);
238
        String username = "public";
239
        String[] groups = null;
240
        if(sessionData != null)
241
        {
242
            username = sessionData.getUserName();
243
            groups = sessionData.getGroupNames();
244
        }
245
        String localId = null;
246

  
247
        if (username == null || username.equals("public"))
248
        {
249
            //TODO: many of the thrown exceptions do not use the correct error codes
250
            //check these against the docs and correct them
251
            throw new NotAuthorized("1100", "User " + username + " is not authorized to create content." +
252
                    "  If you are not logged in, please do so and retry the request.");
253
        }
254
        
255
        // verify that guid == SystemMetadata.getIdentifier()
256
        logMetacat.debug("Comparing guid|sysmeta_guid: " + guid.getValue() + "|" + sysmeta.getIdentifier().getValue());
257
        if (!guid.getValue().equals(sysmeta.getIdentifier().getValue())) {
258
            throw new InvalidSystemMetadata("1180", 
259
                "GUID in method call (" + guid.getValue() + ") does not match GUID in system metadata (" +
260
                sysmeta.getIdentifier().getValue() + ").");
261
        }
262

  
263
        logMetacat.debug("Checking if identifier exists...");
264
        // Check that the identifier does not already exist
265
        IdentifierManager im = IdentifierManager.getInstance();
266
        if (im.identifierExists(guid.getValue())) {
267
            throw new IdentifierNotUnique("1120", 
268
                "GUID is already in use by an existing object.");
269
        }
270

  
271
        // Check if we are handling metadata or data
272
        boolean isScienceMetadata = isScienceMetadata(sysmeta);
273
        
274
        if (isScienceMetadata) {
275
            // CASE METADATA:
276
            try {
277
                //logCrud.debug("CrudService: inserting document with guid " + guid.getValue());
278
                this.insertDocument(object, guid, sessionData);
279
                localId = im.getLocalId(guid.getValue());
280
            } catch (IOException e) {
281
                String msg = "Could not create string from XML stream: " +
282
                    " " + e.getMessage();
283
                logMetacat.debug(msg);
284
                throw new ServiceFailure("1190", msg);
285
            } catch(Exception e) {
286
                String msg = "Unexpected error in CrudService.create: " + e.getMessage();
287
                logMetacat.debug(msg);
288
                throw new ServiceFailure("1190", msg);
289
            }
290
            
291

  
292
        } else {
293
            // DEFAULT CASE: DATA (needs to be checked and completed)
294
            localId = insertDataObject(object, guid, sessionData);
295
            
296
        }
297

  
298
        // For Metadata and Data, insert the system metadata into the object store too
299
        insertSystemMetadata(sysmeta, sessionData);
300
        //get the document info.  add any access params for the sysmeta too
301
        //logCrud.debug("looking for access records to add for system " +
302
        //    "metadata who's parent doc's  local id is " + localId);
303
        try
304
        {
305
            Hashtable<String, Object> h = im.getDocumentInfo(localId.substring(0, localId.lastIndexOf(".")));
306
            Vector v = (Vector)h.get("access");
307
            for(int i=0; i<v.size(); i++)
308
            {
309
                @SuppressWarnings("unchecked")
310
                Hashtable<String, String> ah = (Hashtable<String, String>)v.elementAt(i);
311
                String principal = (String)ah.get("principal_name");
312
                String permission = (String)ah.get("permission");
313
                String permissionType = (String)ah.get("permission_type");
314
                String permissionOrder = (String)ah.get("permission_order");
315
                int perm = new Integer(permission).intValue();
316
                //logCrud.debug("found access record for principal " + principal);
317
                //logCrud.debug("permission: " + perm + " perm_type: " + permissionType + 
318
                //    " perm_order: " + permissionOrder);
319
                this.setAccess(token, guid, principal, perm, permissionType, permissionOrder, true);
320
            }
321
        }
322
        catch(Exception e)
323
        {
324
            logMetacat.error("Error setting permissions on System Metadata object: " +
325
            		e.getMessage());
326
            //TODO: decide if this error should cancel the entire create or
327
            //if it should continue with just a logged error.
328
        }
329
        
330
        
331
        logMetacat.debug("Returning from CrudService.create()");
332
        EventLog.getInstance().log(metacatUrl,
333
                username, localId, "create");
334
        logCrud.info("create D1GUID:" + guid.getValue() + ":D1SCIMETADATA:" + localId);
335
        return guid;
336
    }
337
    
338
    /**
339
     * update an existing object with a new object.  Change the system metadata
340
     * to reflect the changes and update it as well.
341
     */
342
    public Identifier update(AuthToken token, Identifier guid, 
343
            InputStream object, Identifier obsoletedGuid, SystemMetadata sysmeta) 
344
            throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
345
            UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
346
            NotImplemented {
347
    	try
348
    	{
349
    		SessionData sessionData = getSessionData(token);
350
            
351
            //find the old systemmetadata (sm.old) document id (the one linked to obsoletedGuid)
352
            SystemMetadata sm = getSystemMetadata(token, obsoletedGuid);
353
            //change sm.old's obsoletedBy field 
354
            List<Identifier> l = sm.getObsoletedByList();
355
            l.add(guid);
356
            sm.setObsoletedByList(l);
357
            //update sm.old
358
            updateSystemMetadata(sm, sessionData);
359
            
360
            //change the obsoletes field of the new systemMetadata (sm.new) to point to the id of the old one
361
            sysmeta.addObsolete(obsoletedGuid);
362
            //insert sm.new
363
            insertSystemMetadata(sysmeta, sessionData);
364
            String localId;
365
            
366
            boolean isScienceMetadata = isScienceMetadata(sysmeta);
367
            if(isScienceMetadata)
368
            {
369
                //update the doc
370
                localId = updateDocument(object, obsoletedGuid, guid, sessionData, false);
371
            }
372
            else
373
            {
374
                //update a data file, not xml
375
                localId = insertDataObject(object, guid, sessionData);
376
            }
377
            
378
            IdentifierManager im = IdentifierManager.getInstance();
379
            String username = "public";
380
            if(sessionData != null)
381
            {
382
                username = sessionData.getUserName();
383
            }
384
            EventLog.getInstance().log(metacatUrl,
385
                    username, im.getLocalId(guid.getValue()), "update");
386
            logCrud.info("update D1GUID:" + guid.getValue() + ":D1SCIMETADATA:" + localId);
387
            return guid;
388
        }
389

  
390
    	catch(IOException e) {
391
            throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
392
        }
393
    	catch( McdbDocNotFoundException e) {
394
    		throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
395
    	}
396
    	catch( InvalidRequest e) {
397
    		throw new ServiceFailure("1310", "Error updating document in CrudService: " + e.getMessage());
398
    	}
399
    }
400
    
401
    /**
402
     * set access permissions on both the science metadata and system metadata
403
     */
404
    public void setAccess(AuthToken token, Identifier id, String principal, String permission,
405
            String permissionType, String permissionOrder)
406
      throws ServiceFailure
407
    {
408
        setAccess(token, id, principal, permission, permissionType, permissionOrder, true);
409
    }
410
    
411
    /**
412
     * set access control on the doc
413
     * @param token
414
     * @param id
415
     * @param principal
416
     * @param permission
417
     */
418
    public void setAccess(AuthToken token, Identifier id, String principal, int permission,
419
      String permissionType, String permissionOrder, boolean setSystemMetadata)
420
      throws ServiceFailure
421
    {
422
        String perm = "";
423
        if(permission >= 4)
424
        {
425
            perm = "read";
426
        }
427
        if(permission >= 6)
428
        {
429
            perm = "write";
430
        }
431
        //logCrud.debug("perm in setAccess: " + perm);
432
        //logCrud.debug("permission in setAccess: " + permission);
433
        setAccess(token, id, principal, perm, permissionType, permissionOrder,
434
                setSystemMetadata);
435
       
436
    }
437
    
438
    /**
439
     * set the permission on the document
440
     * @param token
441
     * @param principal
442
     * @param permission
443
     * @param permissionType
444
     * @param permissionOrder
445
     * @return
446
     */
447
    public void setAccess(AuthToken token, Identifier id, String principal, String permission,
448
            String permissionType, String permissionOrder, boolean setSystemMetadata)
449
      throws ServiceFailure
450
    {
451
        /* TODO:
452
         * This is also not part of the D1 Crud spec.  This method is needed for
453
         * systems such as metacat where access to objects is controlled by
454
         * and ACL.  Higher level decisions need to be made about how this
455
         * should work within D1.
456
         */
457
        try
458
        {
459
            final SessionData sessionData = getSessionData(token);
460
            if(sessionData == null)
461
            {
462
                throw new ServiceFailure("1000", "User must be logged in to set access.");
463
            }
464
            IdentifierManager im = IdentifierManager.getInstance();
465
            String docid = im.getLocalId(id.getValue());
466
        
467
            String permNum = "0";
468
            if(permission.equals("read"))
469
            {
470
                permNum = "4";
471
            }
472
            else if(permission.equals("write"))
473
            {
474
                permNum = "6";
475
            }
476
            logCrud.debug("user " + sessionData.getUserName() + 
477
                    " is setting access level " + permNum + " for permission " + 
478
                    permissionType + " on doc with localid " + docid);
479
            handler.setAccess(metacatUrl, sessionData.getUserName(), docid, 
480
                    principal, permNum, permissionType, permissionOrder);
481
            
482
            String username = "public";
483
            if(sessionData != null)
484
            {
485
                username = sessionData.getUserName();
486
            }
487
            EventLog.getInstance().log(metacatUrl,
488
                    username, im.getLocalId(id.getValue()), "setAccess");
489
            logCrud.info("setAccess");
490
        }
491
        catch(Exception e)
492
        {
493
            e.printStackTrace();
494
            throw new ServiceFailure("1000", "Could not set access on the document with id " + id.getValue());
495
        }
496
    }
497
    
498
    /**
499
     *  Retrieve the list of objects present on the MN that match the calling 
500
     *  parameters. This method is required to support the process of Member 
501
     *  Node synchronization. At a minimum, this method should be able to 
502
     *  return a list of objects that match:
503
     *  startTime <= SystemMetadata.dateSysMetadataModified
504
     *  but is expected to also support date range (by also specifying endTime), 
505
     *  and should also support slicing of the matching set of records by 
506
     *  indicating the starting index of the response (where 0 is the index 
507
     *  of the first item) and the count of elements to be returned.
508
     *  
509
     *  If startTime or endTime is null, the query is not restricted by that parameter.
510
     *  
511
     * @see http://mule1.dataone.org/ArchitectureDocs/mn_api_replication.html#MN_replication.listObjects
512
     * @param token
513
     * @param startTime
514
     * @param endTime
515
     * @param objectFormat
516
     * @param replicaStatus
517
     * @param start
518
     * @param count
519
     * @return ObjectList
520
     * @throws NotAuthorized
521
     * @throws InvalidRequest
522
     * @throws NotImplemented
523
     * @throws ServiceFailure
524
     * @throws InvalidToken
525
     */
526
    public ObjectList listObjects(AuthToken token, Date startTime, Date endTime, 
527
        ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
528
      throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
529
    {
530
      //ObjectList ol = new ObjectList();
531
      //final SessionData sessionData = getSessionData(token);
532
      //int totalAfterQuery = 0;
533
      
534
      
535
    	ObjectList objectList = null;
536
        try {
537
    	    objectList = IdentifierManager.getInstance().querySystemMetadata(startTime, endTime,
538
    	              objectFormat.getFmtid(), replicaStatus, start, count);
539
        } catch (Exception e) {
... This diff was truncated because it exceeds the maximum size that can be displayed.

Also available in: Unified diff