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.dataone.service.exceptions.InvalidRequest;
45
import org.dataone.service.exceptions.InvalidToken;
46
import org.dataone.service.exceptions.NotAuthorized;
47
import org.dataone.service.exceptions.NotImplemented;
48
import org.dataone.service.exceptions.ServiceFailure;
49
import org.dataone.service.types.*;
50

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

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

    
57
import com.gc.iotools.stream.is.InputStreamFromOutputStream;
58

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

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

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

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

    
368
	        //create the system metadata then run the create method
369
	        String testDoc = getTestDoc();
370
	        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
371
	        SystemMetadata sm = createSystemMetadata(id, testDoc, of1);
372
	        assertFalse(sm.getChecksum().getValue().startsWith("MD5"));
373
	        //create the doc
374
	        Identifier idC = cs.create(token, id, sbis, sm);
375
	        makeDocPublic(token, id, true);
376
	        assertTrue(idC.getValue().equals(id.getValue()));
377
	        SystemMetadata smC = getSystemMetadata(token, idC);
378
	        assertFalse(smC.getChecksum().getValue().startsWith("MD5"));
379
	        
380
	        Date d2 = new Date(new Date().getTime() + 5000);
381
	        
382
	        ObjectList ol = cs.listObjects(token, d1, d2, of1);
383
	        assertTrue(ol.sizeObjectInfoList() > 0);
384
	        ObjectInfo oi = ol.getObjectInfo(0);
385
	        //this will fail if the error state exists.
386
	        assertFalse(oi.getChecksum().getValue().startsWith("MD5"));
387
	    }
388
	    catch(Exception e)
389
	    {
390
	        fail("Unexpected exception: " + e.getMessage());
391
	    }
392
        
393
	}
394
	
395
	/**
396
	 * test CrudService.getLogRecords
397
	 */
398
	public void testGetLogRecords()
399
	{
400
	    printTestHeader("testGetLogRecords");
401
	    try
402
	    {
403
	        CrudService cs = CrudService.getInstance();
404
	        AuthToken token = getToken();
405
	        Date fromDate = new Date();
406
	        Identifier id = createDoc(token, getTestDoc());
407
	        Date toDate = new Date();
408
	        Log lrs = cs.getLogRecords(token, fromDate, toDate, null);
409
	        assertNotNull(lrs);
410
	        System.out.println("log entry size: " + lrs.sizeLogEntryList());
411
	        assertTrue(lrs.sizeLogEntryList() == 1);
412
	        LogEntry lrLogEvent = lrs.getLogEntry(0);
413
	        assertTrue(lrLogEvent.getEvent().name().equals("CREATE"));
414
	        assertTrue(lrLogEvent.getIdentifier().getValue().equals(id.getValue()));
415
	    }
416
	    catch(Exception e)
417
	    {
418
	        e.printStackTrace();
419
	        fail("testGetLogRecords threw an unexpected exception: " + e.getMessage());
420
	    }
421
	}
422
	
423
	/**
424
	 * test the generation of system metadata for docs that don't already 
425
	 * have it.  This will be used for migration of existing object stores
426
	 * to dataone.
427
	 */
428
	public void testGenerateMissingSystemMetadata()
429
	{
430
	    printTestHeader("testGenerateMissingSystemMetadata");
431
	    try
432
	    {
433
	        CrudService cs = CrudService.getInstance();
434
	        AuthToken token = getToken("uid=dataone_cn_metacat,o=DATAONE,dc=ecoinformatics,dc=org", "umtmm4tcn");
435
	        //create a document with no system metadata
436
	        String testDoc = getTestDoc();
437
	        Identifier id = new Identifier();
438
	        String docid = generateDocumentId();
439
	        id.setValue(docid);
440
	        
441
	        cs.insertOrUpdateDocument(testDoc, id, cs.getSessionData(token), "insert", false); 
442
	        //try to get its system metadata, should fail
443
	        try
444
	        {
445
	            getSystemMetadata(token, id);
446
	            fail("call to getSystemMetadata should have failed.");
447
	        }
448
	        catch(Exception e)
449
	        {}
450
	        
451
	        //generate missing system metadata
452
	        cs.generateMissingSystemMetadata(token);
453
	        //try to get system metadata again, should succeed
454
	        getSystemMetadata(token, id);
455
	    }
456
	    catch(Exception e)
457
	    {
458
	        fail("Unexpected error generating missing system metadata: " + e.getMessage());
459
	    }
460
	}
461
	
462
	/**
463
	 * make sure that only valid sessions can update/delete
464
	 */
465
	public void testAccessControl()
466
	{
467
	    printTestHeader("testAccessControl");
468
        try
469
        {
470
            CrudService cs = CrudService.getInstance();
471
            AuthToken token = getToken();
472
            //create a doc
473
            Identifier id = createDoc(token, getTestDoc());
474
            
475
            //get the doc and sysmetadata
476
            String gotDoc = getDoc(token, id);
477
            SystemMetadata sm = getSystemMetadata(token, id);
478
            
479
            //break the session id
480
            String sessionid = "somefakesessionid";
481
            token = new AuthToken(sessionid);
482
            
483
            //update the doc
484
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
485
            Identifier newid = new Identifier();
486
            newid.setValue(generateDocumentId());
487
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
488
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
489
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
490
            fail("exception should have been thrown.");
491
        }
492
        catch(Exception e)
493
        {
494
        }
495
        
496
        try
497
        {
498
            CrudService cs = CrudService.getInstance();
499
            AuthToken token = new AuthToken("somefakesessionid");
500
            //create a doc
501
            Identifier id = createDoc(token, getTestDoc());
502
            fail("exception should have been thrown.");
503
        }
504
        catch(Exception e)
505
        {
506
        }
507
	}
508
	
509
	/**
510
	 * public ObjectList listObjects(AuthToken token, Date startTime, Date endTime, 
511
     *     ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
512
     *       throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
513
	 */
514
	public void testListObjects()
515
	{
516
	    printTestHeader("testListObjects");
517
	    try
518
	    {
519
	        CrudService cs = CrudService.getInstance();
520
	        AuthToken token = getToken();
521
	        ObjectFormat of1 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0");
522
	        ObjectFormat of2 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.0.0");
523
	        //create docs at different times
524
	        Date d1 = new Date();
525
	        Identifier id1 = createDoc(token, getTestDoc(EML2_1_0), of1);
526
            SystemMetadata sm1 = getSystemMetadata(token, id1);
527
            
528
            Date d2 = new Date();
529
            Identifier id2 = createDoc(token, getTestDoc(EML2_0_0), of2);
530
            makeDocPublic(token, id2, true);
531
            SystemMetadata sm2 = getSystemMetadata(token, id2);
532
            
533
            Date d3 = new Date();
534
            Identifier id3 = createDoc(token, getTestDoc(EML2_1_0), of1);
535
            makeDocPublic(token, id3, true);
536
            SystemMetadata sm3 = getSystemMetadata(token, id3);
537
              
538
            Date d4 = new Date();
539
            Identifier id4 = createDoc(token, getTestDoc(EML2_0_0), of2);
540
            makeDocPublic(token, id4, true);
541
            SystemMetadata sm4 = getSystemMetadata(token, id4);
542
            
543
            Date d5 = new Date();
544
            Identifier id5 = createDoc(token, getTestDoc(EML2_1_0), of1);
545
            makeDocPublic(token, id5, true);
546
            SystemMetadata sm5 = getSystemMetadata(token, id5);  
547
             
548
            Date d6 = new Date();
549
            
550
            //now get the objects for specific time ranges and test that it returns
551
            //the correct objects
552
            
553
            //ObjectList list = cs.listObjects(token, null, null, null);
554
            //System.out.println("list size: " + list.sizeObjectInfoList());
555
           
556
            //should return sm1 and sm2
557
            ObjectList list1 = cs.listObjects(token, d1, d3, null);
558
            assertTrue(list1.sizeObjectInfoList() == 2);
559
            assertTrue(idInObjectList(id1, list1));
560
            assertTrue(idInObjectList(id2, list1));
561
            
562
            ObjectInfo info = list1.getObjectInfo(0);
563
            
564
            
565
            //should only return sm1
566
            ObjectList list2 = cs.listObjects(token, d1, d3, of1);
567
            assertTrue(list2.sizeObjectInfoList() == 1);
568
            assertTrue(idInObjectList(id1, list2));
569
            
570
            //should return sm1-sm4
571
            ObjectList list3 = cs.listObjects(token, d1, d5, null);
572
            assertTrue(list3.sizeObjectInfoList() == 4);
573
            ObjectInfo oi4 = list3.getObjectInfo(0);
574
            assertTrue(idInObjectList(id1, list3));
575
            assertTrue(idInObjectList(id2, list3));
576
            assertTrue(idInObjectList(id3, list3));
577
            assertTrue(idInObjectList(id4, list3));
578
            
579
            //should only return sm2 and sm4
580
            ObjectList list4 = cs.listObjects(token, d1, d5, of2);
581
            assertTrue(list4.sizeObjectInfoList() == 2);
582
            assertTrue(idInObjectList(id2, list4));
583
            assertTrue(idInObjectList(id4, list4));
584
            
585
            //should return all
586
            ObjectList list5 = cs.listObjects(token, d1, d6, null);
587
            assertTrue(list5.sizeObjectInfoList() == 5);
588
            assertTrue(idInObjectList(id1, list5));
589
            assertTrue(idInObjectList(id2, list5));
590
            assertTrue(idInObjectList(id3, list5));
591
            assertTrue(idInObjectList(id4, list5));
592
            assertTrue(idInObjectList(id5, list5));
593
            
594
            //should return 1, 3, 5
595
            ObjectList list6 = cs.listObjects(token, d1, d6, of1);
596
            assertTrue(list6.sizeObjectInfoList() == 3);
597
            assertTrue(idInObjectList(id1, list6));
598
            assertTrue(idInObjectList(id3, list6));
599
            assertTrue(idInObjectList(id5, list6));
600
            
601
            //should return 4 (id1 is not public)
602
            token = new AuthToken("public");
603
            ObjectList list7 = cs.listObjects(token, d1, d6, null);
604
            //System.out.println("list7 size: " + list7.sizeObjectInfoList());
605
            assertTrue(list7.sizeObjectInfoList() == 5);
606
            
607
            //test paging
608
            ObjectList list8 = cs.listObjects(token, d1, d6, null, false, 2, 2);
609
            assertTrue(list8.getCount() == 2);
610
            assertTrue(list8.getStart() == 2);
611
            assertTrue(list8.getTotal() == 5);
612
            
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
	private String getTestDoc()
804
	{
805
	    return getTestDoc(null);
806
	}
807
	
808
	/**
809
	 * return a test document.  objectFormat should come from MCTestCase
810
	 */
811
	private String getTestDoc(String objectFormat)
812
	{
813
	    if(objectFormat == null)
814
	    {
815
	        return "<?xml version=\"1.0\"?><test><somecontent>This is some content XXX</somecontent></test>\n";
816
	    }
817
	    
818
	    String accessBlock = getAccessBlock("public", true, true,
819
                false, false, false);
820
	    
821
	    
822
	    return getTestEmlDoc("Test identifier manager", objectFormat, null,
823
	                null, "http://fake.example.com/somedata", null,
824
	                accessBlock, null, null,
825
	                null, null);
826
	}
827
	
828
	/**
829
	 * authenticate and return a token
830
	 * use the test.mcUser and test.mcPassword username/password combo
831
	 */
832
	private AuthToken getToken()
833
	  throws Exception
834
	{
835
        String username = PropertyService.getProperty("test.mcUser");
836
        String password = PropertyService.getProperty("test.mcPassword");
837
        return getToken(username, password);
838
	}
839
	
840
	/**
841
	 * authenticate and return a token using the given credentials
842
	 */
843
	private AuthToken getToken(String username, String password)
844
	  throws Exception
845
	{
846
	    CrudService cs = CrudService.getInstance();
847
        //login and get a sessionid
848
        MetacatRestClient restClient = new MetacatRestClient(cs.getContextUrl());
849
        String response = restClient.login(username, password);
850
        String sessionid = restClient.getSessionId();
851
        SessionService sessionService = SessionService.getInstance();
852
        sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
853
        AuthToken token = new AuthToken(sessionid);
854
        return token;
855
	}
856
	
857
	/**
858
	 * create a doc using CrudService.create() and return its id
859
	 */
860
	private Identifier createDoc(AuthToken token, String testDoc) throws Exception
861
	{
862
	    return createDoc(token, testDoc, ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
863
	}
864
	
865
	/**
866
	 * create a doc using CrudService.create() and return its id
867
	 */
868
	private Identifier createDoc(AuthToken token, String testDoc, ObjectFormat format) throws Exception
869
	{
870
	    Identifier id;
871
        CrudService cs = CrudService.getInstance();
872
        
873
        id = new Identifier();
874
        String docid = generateDocumentId();
875
        id.setValue(docid);
876
        
877
        //create the system metadata then run the create method
878
        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
879
        SystemMetadata sm = createSystemMetadata(id, testDoc, format);
880
        //create the doc
881
        cs.create(token, id, sbis, sm);
882
        createCount++;
883
        return id;
884
	}
885
	
886
	/**
887
	 * create a generic SystemMetadata object for testing
888
	 */
889
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc)
890
	  throws Exception
891
	{
892
	    return createSystemMetadata(id, testDoc, 
893
	            ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
894
	}
895
	
896
	/**
897
	 * create system metadata with a specified id, doc and format
898
	 */
899
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc, ObjectFormat format)
900
	  throws Exception
901
	{
902
	    SystemMetadata sm = new SystemMetadata();
903
        //set the id
904
        sm.setIdentifier(id);
905
        sm.setObjectFormat(format);
906
        //create the checksum
907
        String checksumS = checksum(testDoc);
908
        ChecksumAlgorithm ca = ChecksumAlgorithm.convert("MD5");
909
        Checksum checksum = new Checksum();
910
        checksum.setValue(checksumS);
911
        checksum.setAlgorithm(ca);
912
        sm.setChecksum(checksum);
913
        //set the size
914
        sm.setSize(testDoc.getBytes(MetaCatServlet.DEFAULT_ENCODING).length);
915
        //submitter
916
        Principal p = new Principal();
917
        p.setValue("joe");
918
        sm.setSubmitter(p);
919
        sm.setRightsHolder(p);
920
        sm.setDateUploaded(new Date());
921
        sm.setDateSysMetadataModified(new Date());
922
        NodeReference nr = new NodeReference();
923
        nr.setValue("metacat");
924
        sm.setOriginMemberNode(nr);
925
        sm.setAuthoritativeMemberNode(nr);
926
        return sm;
927
	}
928
	
929
	/**
930
	 *  make a document public in metacat by inserting an access document
931
	 * @param id
932
	 */
933
	private void makeDocPublic(AuthToken token, Identifier id, boolean systemMetadataToo)
934
	  throws Exception
935
	{
936
	    CrudService cs = CrudService.getInstance();
937
	    cs.setAccess(token, id, "public", "read", "allow", "allowFirst", systemMetadataToo);
938
	}
939
	
940
	/**
941
	 * print a header to start each test
942
	 */
943
	private void printTestHeader(String testName)
944
	{
945
	    System.out.println();
946
	    System.out.println("*************** " + testName + " ***************");
947
	}
948
  
949
	/**
950
	 * produce an md5 checksum for item
951
	 */
952
	private String checksum(String item)
953
	  throws Exception
954
	{
955
        StringBufferInputStream fis =  new StringBufferInputStream(item);
956
        
957
        byte[] buffer = new byte[1024];
958
        MessageDigest complete = MessageDigest.getInstance("MD5");
959
        int numRead;
960
        
961
        do 
962
        {
963
          numRead = fis.read(buffer);
964
          if (numRead > 0) 
965
          {
966
            complete.update(buffer, 0, numRead);
967
          }
968
        } while (numRead != -1);
969
        
970
        
971
        return getHex(complete.digest());
972
	}
973
	
974
	/**
975
	 * convert a byte array to a hex string
976
	 */
977
	private static String getHex( byte [] raw ) 
978
	{
979
	    final String HEXES = "0123456789ABCDEF";
980
        if ( raw == null ) {
981
          return null;
982
        }
983
        final StringBuilder hex = new StringBuilder( 2 * raw.length );
984
        for ( final byte b : raw ) {
985
          hex.append(HEXES.charAt((b & 0xF0) >> 4))
986
             .append(HEXES.charAt((b & 0x0F)));
987
        }
988
        return hex.toString();
989
    }
990
}
(1-1/3)