Project

General

Profile

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.util.*;
29
import java.io.*;
30

    
31
import java.security.MessageDigest;
32

    
33
import edu.ucsb.nceas.MCTestCase;
34
import edu.ucsb.nceas.metacat.IdentifierManager;
35
import edu.ucsb.nceas.metacat.MetaCatServlet;
36
import edu.ucsb.nceas.metacat.client.MetacatAuthException;
37
import edu.ucsb.nceas.metacat.client.MetacatException;
38
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
39
import edu.ucsb.nceas.metacat.dataone.CrudService;
40
import junit.framework.Test;
41
import junit.framework.TestSuite;
42

    
43
import org.apache.commons.io.IOUtils;
44
import org.apache.log.LogEvent;
45
import org.dataone.service.exceptions.InvalidRequest;
46
import org.dataone.service.exceptions.InvalidToken;
47
import org.dataone.service.exceptions.NotAuthorized;
48
import org.dataone.service.exceptions.NotImplemented;
49
import org.dataone.service.exceptions.ServiceFailure;
50
import org.dataone.service.types.*;
51

    
52
import edu.ucsb.nceas.metacat.properties.PropertyService;
53
import edu.ucsb.nceas.metacat.client.rest.MetacatRestClient;
54

    
55
import edu.ucsb.nceas.metacat.service.SessionService;
56
import edu.ucsb.nceas.metacat.util.SessionData;
57

    
58
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
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
		suite.addTest(new CrudServiceTest("testSingletonAccessor"));
99
		suite.addTest(new CrudServiceTest("testCreateAndGet"));
100
		suite.addTest(new CrudServiceTest("testGetSystemMetadata"));
101
		suite.addTest(new CrudServiceTest("testUpdate"));
102
		suite.addTest(new CrudServiceTest("testListObjects"));
103
		suite.addTest(new CrudServiceTest("testAccessControl"));*/
104
		suite.addTest(new CrudServiceTest("testGenerateMissingSystemMetadata"));
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
                    ObjectFormat.convert("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().toString()));
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 = ObjectFormat.convert("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 = ObjectFormat.convert("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 = ObjectFormat.convert("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
	 * test the generation of system metadata for docs that don't already 
426
	 * have it.  This will be used for migration of existing object stores
427
	 * to dataone.
428
	 */
429
	public void testGenerateMissingSystemMetadata()
430
	{
431
	    printTestHeader("testGenerateMissingSystemMetadata");
432
	    try
433
	    {
434
	        CrudService cs = CrudService.getInstance();
435
	        AuthToken token = getToken("uid=dataone_cn_metacat,o=DATAONE,dc=ecoinformatics,dc=org", "umtmm4tcn");
436
	        //create a document with no system metadata
437
	        String testDoc = getTestDoc();
438
	        Identifier id = new Identifier();
439
	        String docid = generateDocumentId();
440
	        id.setValue(docid);
441
	        
442
	        cs.insertOrUpdateDocument(testDoc, id, cs.getSessionData(token), "insert", false); 
443
	        //try to get its system metadata, should fail
444
	        try
445
	        {
446
	            getSystemMetadata(token, id);
447
	            fail("call to getSystemMetadata should have failed.");
448
	        }
449
	        catch(Exception e)
450
	        {}
451
	        
452
	        //generate missing system metadata
453
	        cs.generateMissingSystemMetadata(token);
454
	        //try to get system metadata again, should succeed
455
	        getSystemMetadata(token, id);
456
	    }
457
	    catch(Exception e)
458
	    {
459
	        fail("Unexpected error generating missing system metadata: " + e.getMessage());
460
	    }
461
	}
462
	
463
	/**
464
	 * make sure that only valid sessions can update/delete
465
	 */
466
	public void testAccessControl()
467
	{
468
	    printTestHeader("testAccessControl");
469
        try
470
        {
471
            CrudService cs = CrudService.getInstance();
472
            AuthToken token = getToken();
473
            //create a doc
474
            Identifier id = createDoc(token, getTestDoc());
475
            
476
            //get the doc and sysmetadata
477
            String gotDoc = getDoc(token, id);
478
            SystemMetadata sm = getSystemMetadata(token, id);
479
            
480
            //break the session id
481
            String sessionid = "somefakesessionid";
482
            token = new AuthToken(sessionid);
483
            
484
            //update the doc
485
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
486
            Identifier newid = new Identifier();
487
            newid.setValue(generateDocumentId());
488
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
489
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
490
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
491
            fail("exception should have been thrown.");
492
        }
493
        catch(Exception e)
494
        {
495
        }
496
        
497
        try
498
        {
499
            CrudService cs = CrudService.getInstance();
500
            AuthToken token = new AuthToken("somefakesessionid");
501
            //create a doc
502
            Identifier id = createDoc(token, getTestDoc());
503
            fail("exception should have been thrown.");
504
        }
505
        catch(Exception e)
506
        {
507
        }
508
	}
509
	
510
	/**
511
	 * public ObjectList listObjects(AuthToken token, Date startTime, Date endTime, 
512
     *     ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
513
     *       throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
514
	 */
515
	public void testListObjects()
516
	{
517
	    printTestHeader("testListObjects");
518
	    try
519
	    {
520
	        CrudService cs = CrudService.getInstance();
521
	        AuthToken token = getToken();
522
	        ObjectFormat of1 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0");
523
	        ObjectFormat of2 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.0.0");
524
	        //create docs at different times
525
	        Date d1 = new Date();
526
	        Identifier id1 = createDoc(token, getTestDoc(), of1);
527
            SystemMetadata sm1 = getSystemMetadata(token, id1);
528
            
529
            Date d2 = new Date();
530
            Identifier id2 = createDoc(token, getTestDoc(), of2);
531
            makeDocPublic(token, id2, true);
532
            SystemMetadata sm2 = getSystemMetadata(token, id2);
533
            
534
            Date d3 = new Date();
535
            Identifier id3 = createDoc(token, getTestDoc(), of1);
536
            makeDocPublic(token, id3, true);
537
            SystemMetadata sm3 = getSystemMetadata(token, id3);
538
              
539
            Date d4 = new Date();
540
            Identifier id4 = createDoc(token, getTestDoc(), of2);
541
            makeDocPublic(token, id4, true);
542
            SystemMetadata sm4 = getSystemMetadata(token, id4);
543
            
544
            Date d5 = new Date();
545
            Identifier id5 = createDoc(token, getTestDoc(), of1);
546
            makeDocPublic(token, id5, true);
547
            SystemMetadata sm5 = getSystemMetadata(token, id5);  
548
             
549
            Date d6 = new Date();
550
            
551
            //now get the objects for specific time ranges and test that it returns
552
            //the correct objects
553
            
554
            //ObjectList list = cs.listObjects(token, null, null, null);
555
            //System.out.println("list size: " + list.sizeObjectInfoList());
556
           
557
            //should return sm1 and sm2
558
            ObjectList list1 = cs.listObjects(token, d1, d3, null);
559
            assertTrue(list1.sizeObjectInfoList() == 2);
560
            assertTrue(idInObjectList(id1, list1));
561
            assertTrue(idInObjectList(id2, list1));
562
            
563
            ObjectInfo info = list1.getObjectInfo(0);
564
            
565
            
566
            //should only return sm1
567
            ObjectList list2 = cs.listObjects(token, d1, d3, of1);
568
            assertTrue(list2.sizeObjectInfoList() == 1);
569
            assertTrue(idInObjectList(id1, list2));
570
            
571
            //should return sm1-sm4
572
            ObjectList list3 = cs.listObjects(token, d1, d5, null);
573
            assertTrue(list3.sizeObjectInfoList() == 4);
574
            ObjectInfo oi4 = list3.getObjectInfo(0);
575
            assertTrue(idInObjectList(id1, list3));
576
            assertTrue(idInObjectList(id2, list3));
577
            assertTrue(idInObjectList(id3, list3));
578
            assertTrue(idInObjectList(id4, list3));
579
            
580
            //should only return sm2 and sm4
581
            ObjectList list4 = cs.listObjects(token, d1, d5, of2);
582
            assertTrue(list4.sizeObjectInfoList() == 2);
583
            assertTrue(idInObjectList(id2, list4));
584
            assertTrue(idInObjectList(id4, list4));
585
            
586
            //should return all
587
            ObjectList list5 = cs.listObjects(token, d1, d6, null);
588
            assertTrue(list5.sizeObjectInfoList() == 5);
589
            assertTrue(idInObjectList(id1, list5));
590
            assertTrue(idInObjectList(id2, list5));
591
            assertTrue(idInObjectList(id3, list5));
592
            assertTrue(idInObjectList(id4, list5));
593
            assertTrue(idInObjectList(id5, list5));
594
            
595
            //should return 1, 3, 5
596
            ObjectList list6 = cs.listObjects(token, d1, d6, of1);
597
            assertTrue(list6.sizeObjectInfoList() == 3);
598
            assertTrue(idInObjectList(id1, list6));
599
            assertTrue(idInObjectList(id3, list6));
600
            assertTrue(idInObjectList(id5, list6));
601
            
602
            //should return 4 (id1 is not public)
603
            token = new AuthToken("public");
604
            ObjectList list7 = cs.listObjects(token, d1, d6, null);
605
            //System.out.println("list7 size: " + list7.sizeObjectInfoList());
606
            assertTrue(list7.sizeObjectInfoList() == 4);
607
            
608
            //test paging
609
            ObjectList list8 = cs.listObjects(token, d1, d6, null, false, 2, 2);
610
            assertTrue(list8.getCount() == 2);
611
            assertTrue(list8.getStart() == 2);
612
            assertTrue(list8.getTotal() == 4);
613
            
614
	    }
615
	    catch(Exception e)
616
	    {
617
	        //e.printStackTrace();
618
	        fail("Error in listObjects: " + e.getMessage());
619
	    }
620
	}
621
	
622
	private boolean idInObjectList(Identifier id, ObjectList list)
623
	{
624
	    for(int i=0; i<list.sizeObjectInfoList(); i++)
625
	    {
626
	        ObjectInfo oi = list.getObjectInfo(i);
627
	        if(id.getValue().equals(oi.getIdentifier().getValue()))
628
	            return true;
629
	    }
630
	    return false;
631
	}
632
	
633
	/**
634
	 * public Identifier update(AuthToken token, Identifier guid, 
635
     *       InputStream object, Identifier obsoletedGuid, SystemMetadata sysmeta) 
636
     *         throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
637
     *           UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
638
     *           NotImplemented
639
	 */
640
	public void testUpdate()
641
	{
642
	    printTestHeader("testUpdate");
643
	    try
644
	    {
645
	        CrudService cs = CrudService.getInstance();
646
	        AuthToken token = getToken();
647
            //create a doc
648
            Identifier id = createDoc(token, getTestDoc());
649
            
650
            //get the doc and sysmetadata
651
            String gotDoc = getDoc(token, id);
652
            SystemMetadata sm = getSystemMetadata(token, id);
653
            
654
            //update the doc
655
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
656
            Identifier newid = new Identifier();
657
            newid.setValue(generateDocumentId());
658
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
659
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
660
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
661
            
662
            //get doc - check that it matches update
663
            String newdoc = getDoc(token, newid);
664
            assertTrue(gotDoc.equals(newdoc));
665
            
666
            //get sysmeta - check that ids and other fields are updated
667
            SystemMetadata newnewsm = getSystemMetadata(token, id);
668
            assertTrue(newnewsm.getObsoletedBy(0).getValue().equals(newid.getValue()));
669
            
670
            //get the new sysmeta and make sure the obsoletes field is set
671
            SystemMetadata newnewnewsm = getSystemMetadata(token, newid);
672
            assertTrue(newnewnewsm.getObsolete(0).getValue().equals(id.getValue()));
673
        }
674
        catch(Exception e)
675
        {
676
            e.printStackTrace();
677
            fail("Error in testUpdate: " + e.getMessage());
678
        }
679
	}
680
	
681
	/**
682
	 * public SystemMetadata getSystemMetadata(AuthToken token, Identifier guid)
683
     *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
684
     *       InvalidRequest, NotImplemented
685
	 */
686
	public void testGetSystemMetadata()
687
	{
688
	    printTestHeader("testGetSystemMetadata");
689
	    try
690
	    {
691
            CrudService cs = CrudService.getInstance();
692
            AuthToken token = getToken();
693
            //run create
694
            Identifier id = createDoc(token, getTestDoc());
695
            //get the systemMetadata and make sure it is the correct object for this testDoc
696
            SystemMetadata sm = getSystemMetadata(token, id);
697
            assertTrue(sm.getIdentifier().getValue().equals(id.getValue()));
698
            assertTrue(sm.getChecksum().getValue().equals(checksum(getTestDoc())));
699
            
700
            try
701
            {
702
                Identifier fakeid = new Identifier();
703
                fakeid.setValue("somethingfake.234234");
704
                getSystemMetadata(token, fakeid);
705
                fail("getSystemMetadata should have thrown an exception.");
706
            }
707
            catch(Exception e)
708
            {
709
                assertTrue(true);
710
            }
711
        }
712
        catch(Exception e)
713
        {
714
            e.printStackTrace();
715
            fail("Error testing system metadata: " + e.getMessage());
716
        }
717
	}
718
	
719
	/**
720
	 * create(AuthToken token, Identifier guid, InputStream object, SystemMetadata sysmeta) 
721
     *   throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
722
     *       InsufficientResources, InvalidSystemMetadata, NotImplemented
723
     *
724
     * public InputStream get(AuthToken token, Identifier guid)
725
     *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
726
     *       NotImplemented
727
	 */
728
	public void testCreateAndGet()
729
	{
730
	    printTestHeader("testCreateAndGet");
731
	    try
732
	    {
733
	        CrudService cs = CrudService.getInstance();
734
	        AuthToken token = getToken();
735
	        //run create
736
	        Identifier id = createDoc(token, getTestDoc());
737
	        //make these docs public for debugging purposes.
738
	        makeDocPublic(token, id, true);
739
            //compare the docs
740
            String gotDoc = getDoc(token, id);
741
            assertTrue(gotDoc.trim().equals(getTestDoc().trim()));
742
            
743
            try
744
            {
745
                Identifier fakeid = new Identifier();
746
                fakeid.setValue("somethingfake.234234");
747
                getDoc(token, fakeid);
748
                fail("testCreateAndGet should have thrown an exception.");
749
            }
750
            catch(Exception e)
751
            {
752
                assertTrue(true);
753
            }
754
        }
755
        catch(Exception e)
756
        {
757
            e.printStackTrace();
758
            fail("Error in testCreate: " + e.getMessage());
759
        }
760
	}
761

    
762
	/**
763
	 * getInstance()
764
	 */
765
	public void testSingletonAccessor()
766
	{
767
	    printTestHeader("testSingletonAccessor");
768
	    CrudService cs = CrudService.getInstance();
769
	    assertNotNull(cs);
770
	}
771
	
772
	/**
773
	 * Run an initial test that always passes to check that the test harness is
774
	 * working.
775
	 */
776
	public void initialize() 
777
	{
778
	    printTestHeader("initialize");
779
		assertTrue(1 == 1);
780
	}
781
	
782
	/**
783
	 * return the systemMetadata object for id
784
	 */
785
	private SystemMetadata getSystemMetadata(AuthToken token, Identifier id)
786
	  throws Exception
787
	{
788
	    CrudService cs = CrudService.getInstance();
789
	    return cs.getSystemMetadata(token, id);
790
	}
791
	
792
	/**
793
	 * get a doc from metacat using CrudService.get()
794
	 */
795
	private String getDoc(AuthToken token, Identifier id)
796
	  throws Exception
797
	{
798
	    CrudService cs = CrudService.getInstance();
799
        InputStream gotDocStream = cs.get(token, id);
800
        return IOUtils.toString(gotDocStream);
801
	}
802
	
803
	/**
804
	 * return a test document
805
	 */
806
	private String getTestDoc()
807
	{
808
	    return "<?xml version=\"1.0\"?><test><somecontent>This is some content XXX</somecontent></test>\n";
809
	}
810
	
811
	/**
812
	 * authenticate and return a token
813
	 * use the test.mcUser and test.mcPassword username/password combo
814
	 */
815
	private AuthToken getToken()
816
	  throws Exception
817
	{
818
        String username = PropertyService.getProperty("test.mcUser");
819
        String password = PropertyService.getProperty("test.mcPassword");
820
        return getToken(username, password);
821
	}
822
	
823
	/**
824
	 * authenticate and return a token using the given credentials
825
	 */
826
	private AuthToken getToken(String username, String password)
827
	  throws Exception
828
	{
829
	    CrudService cs = CrudService.getInstance();
830
        //login and get a sessionid
831
        MetacatRestClient restClient = new MetacatRestClient(cs.getContextUrl());
832
        String response = restClient.login(username, password);
833
        String sessionid = restClient.getSessionId();
834
        SessionService sessionService = SessionService.getInstance();
835
        sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
836
        AuthToken token = new AuthToken(sessionid);
837
        return token;
838
	}
839
	
840
	/**
841
	 * create a doc using CrudService.create() and return its id
842
	 */
843
	private Identifier createDoc(AuthToken token, String testDoc) throws Exception
844
	{
845
	    return createDoc(token, testDoc, ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
846
	}
847
	
848
	/**
849
	 * create a doc using CrudService.create() and return its id
850
	 */
851
	private Identifier createDoc(AuthToken token, String testDoc, ObjectFormat format) throws Exception
852
	{
853
	    Identifier id;
854
        CrudService cs = CrudService.getInstance();
855
        
856
        id = new Identifier();
857
        String docid = generateDocumentId();
858
        id.setValue(docid);
859
        
860
        //create the system metadata then run the create method
861
        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
862
        SystemMetadata sm = createSystemMetadata(id, testDoc, format);
863
        //create the doc
864
        cs.create(token, id, sbis, sm);
865
        createCount++;
866
        return id;
867
	}
868
	
869
	/**
870
	 * create a generic SystemMetadata object for testing
871
	 */
872
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc)
873
	  throws Exception
874
	{
875
	    return createSystemMetadata(id, testDoc, 
876
	            ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
877
	}
878
	
879
	/**
880
	 * create system metadata with a specified id, doc and format
881
	 */
882
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc, ObjectFormat format)
883
	  throws Exception
884
	{
885
	    SystemMetadata sm = new SystemMetadata();
886
        //set the id
887
        sm.setIdentifier(id);
888
        sm.setObjectFormat(format);
889
        //create the checksum
890
        String checksumS = checksum(testDoc);
891
        ChecksumAlgorithm ca = ChecksumAlgorithm.convert("MD5");
892
        Checksum checksum = new Checksum();
893
        checksum.setValue(checksumS);
894
        checksum.setAlgorithm(ca);
895
        sm.setChecksum(checksum);
896
        //set the size
897
        sm.setSize(testDoc.getBytes(MetaCatServlet.DEFAULT_ENCODING).length);
898
        //submitter
899
        Principal p = new Principal();
900
        p.setValue("joe");
901
        sm.setSubmitter(p);
902
        sm.setRightsHolder(p);
903
        sm.setDateUploaded(new Date());
904
        sm.setDateSysMetadataModified(new Date());
905
        NodeReference nr = new NodeReference();
906
        nr.setValue("metacat");
907
        sm.setOriginMemberNode(nr);
908
        sm.setAuthoritativeMemberNode(nr);
909
        return sm;
910
	}
911
	
912
	/**
913
	 *  make a document public in metacat by inserting an access document
914
	 * @param id
915
	 */
916
	private void makeDocPublic(AuthToken token, Identifier id, boolean systemMetadataToo)
917
	  throws Exception
918
	{
919
	    CrudService cs = CrudService.getInstance();
920
	    cs.setAccess(token, id, "public", "read", "allow", "allowFirst", systemMetadataToo);
921
	}
922
	
923
	/**
924
	 * print a header to start each test
925
	 */
926
	private void printTestHeader(String testName)
927
	{
928
	    System.out.println();
929
	    System.out.println("*************** " + testName + " ***************");
930
	}
931
  
932
	/**
933
	 * produce an md5 checksum for item
934
	 */
935
	private String checksum(String item)
936
	  throws Exception
937
	{
938
        StringBufferInputStream fis =  new StringBufferInputStream(item);
939
        
940
        byte[] buffer = new byte[1024];
941
        MessageDigest complete = MessageDigest.getInstance("MD5");
942
        int numRead;
943
        
944
        do 
945
        {
946
          numRead = fis.read(buffer);
947
          if (numRead > 0) 
948
          {
949
            complete.update(buffer, 0, numRead);
950
          }
951
        } while (numRead != -1);
952
        
953
        
954
        return getHex(complete.digest());
955
	}
956
	
957
	/**
958
	 * convert a byte array to a hex string
959
	 */
960
	private static String getHex( byte [] raw ) 
961
	{
962
	    final String HEXES = "0123456789ABCDEF";
963
        if ( raw == null ) {
964
          return null;
965
        }
966
        final StringBuilder hex = new StringBuilder( 2 * raw.length );
967
        for ( final byte b : raw ) {
968
          hex.append(HEXES.charAt((b & 0xF0) >> 4))
969
             .append(HEXES.charAt((b & 0x0F)));
970
        }
971
        return hex.toString();
972
    }
973
}
(1-1/3)