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.client.MetacatAuthException;
36
import edu.ucsb.nceas.metacat.client.MetacatException;
37
import edu.ucsb.nceas.metacat.client.MetacatInaccessibleException;
38
import edu.ucsb.nceas.metacat.dataone.CrudService;
39
import junit.framework.Test;
40
import junit.framework.TestSuite;
41

    
42
import org.dataone.service.exceptions.InvalidRequest;
43
import org.dataone.service.exceptions.InvalidToken;
44
import org.dataone.service.exceptions.NotAuthorized;
45
import org.dataone.service.exceptions.NotImplemented;
46
import org.dataone.service.exceptions.ServiceFailure;
47
import org.dataone.service.types.*;
48

    
49
import edu.ucsb.nceas.metacat.properties.PropertyService;
50
import edu.ucsb.nceas.metacat.client.rest.MetacatRestClient;
51

    
52
import edu.ucsb.nceas.metacat.service.SessionService;
53
import edu.ucsb.nceas.metacat.util.SessionData;
54

    
55
/**
56
 * A JUnit test for testing the dataone CrudService class
57
 */
58
public class CrudServiceTest extends MCTestCase 
59
{   
60
    /**
61
    * consstructor for the test
62
    */
63
    public CrudServiceTest(String name)
64
    {
65
        super(name);
66
    }
67
  
68
    /**
69
	 * Establish a testing framework by initializing appropriate objects
70
	 */
71
	public void setUp() throws Exception 
72
	{
73
		super.setUp();
74
	}
75

    
76
	/**
77
	 * Release any objects after tests are complete
78
	 */
79
	public void tearDown() 
80
	{
81
	}
82

    
83
	/**
84
	 * Create a suite of tests to be run together
85
	 */
86
	public static Test suite() 
87
	{
88
		TestSuite suite = new TestSuite();
89
		suite.addTest(new CrudServiceTest("initialize"));
90
		suite.addTest(new CrudServiceTest("testSingletonAccessor"));
91
		suite.addTest(new CrudServiceTest("testCreateAndGet"));
92
		suite.addTest(new CrudServiceTest("testGetSystemMetadata"));
93
		suite.addTest(new CrudServiceTest("testUpdate"));
94
		suite.addTest(new CrudServiceTest("testListObjects"));
95
		suite.addTest(new CrudServiceTest("testAccessControl"));
96
		//suite.addTest(new CrudServiceTest(""));
97
		return suite;
98
	}
99
	
100
	/**
101
	 * make sure that only valid sessions can update/delete
102
	 */
103
	public void testAccessControl()
104
	{
105
        try
106
        {
107
            CrudService cs = CrudService.getInstance();
108
            AuthToken token = getToken();
109
            //create a doc
110
            Identifier id = createDoc(token, getTestDoc());
111
            
112
            //get the doc and sysmetadata
113
            String gotDoc = getDoc(token, id);
114
            SystemMetadata sm = getSystemMetadata(token, id);
115
            
116
            //break the session id
117
            String sessionid = "somefakesessionid";
118
            token = new AuthToken(sessionid);
119
            
120
            //update the doc
121
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
122
            Identifier newid = new Identifier();
123
            newid.setValue(generateDocumentId());
124
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
125
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
126
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
127
            fail("exception should have been thrown.");
128
        }
129
        catch(Exception e)
130
        {
131
        }
132
        
133
        try
134
        {
135
            CrudService cs = CrudService.getInstance();
136
            AuthToken token = new AuthToken("somefakesessionid");
137
            //create a doc
138
            Identifier id = createDoc(token, getTestDoc());
139
            fail("exception should have been thrown.");
140
        }
141
        catch(Exception e)
142
        {
143
        }
144
	}
145
	
146
	/**
147
	 * public ObjectList listObjects(AuthToken token, Date startTime, Date endTime, 
148
     *     ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
149
     *       throws NotAuthorized, InvalidRequest, NotImplemented, ServiceFailure, InvalidToken
150
	 */
151
	public void testListObjects()
152
	{
153
	    printTestHeader("testListObjects");
154
	    try
155
	    {
156
	        CrudService cs = CrudService.getInstance();
157
	        AuthToken token = getToken();
158
	        ObjectFormat of1 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0");
159
	        ObjectFormat of2 = ObjectFormat.convert("eml://ecoinformatics.org/eml-2.0.0");
160
	        //create docs at different times
161
	        Date d1 = new Date();
162
	        Identifier id1 = createDoc(token, getTestDoc(), of1);
163
            SystemMetadata sm1 = getSystemMetadata(token, id1);
164
            
165
            Date d2 = new Date();
166
            Identifier id2 = createDoc(token, getTestDoc(), of2);
167
            SystemMetadata sm2 = getSystemMetadata(token, id2);
168
            
169
            Date d3 = new Date();
170
            Identifier id3 = createDoc(token, getTestDoc(), of1);
171
            SystemMetadata sm3 = getSystemMetadata(token, id3);
172
              
173
            Date d4 = new Date();
174
            Identifier id4 = createDoc(token, getTestDoc(), of2);
175
            SystemMetadata sm4 = getSystemMetadata(token, id4);
176
            
177
            Date d5 = new Date();
178
            Identifier id5 = createDoc(token, getTestDoc(), of1);
179
            SystemMetadata sm5 = getSystemMetadata(token, id5);  
180
             
181
            Date d6 = new Date();
182
            
183
            //now get the objects for specific time ranges and test that it returns
184
            //the correct objects
185
            
186
            ObjectList list = cs.listObjects(token, null, null, null);
187
            //System.out.println("list size: " + list.sizeObjectInfoList());
188
	        
189
            //should return sm1 and sm2
190
            ObjectList list1 = cs.listObjects(token, d1, d3, null);
191
            assertTrue(list1.sizeObjectInfoList() == 2);
192
            assertTrue(idInObjectList(id1, list1));
193
            assertTrue(idInObjectList(id2, list1));
194
            
195
            //should only return sm1
196
            ObjectList list2 = cs.listObjects(token, d1, d3, of1);
197
            assertTrue(list2.sizeObjectInfoList() == 1);
198
            assertTrue(idInObjectList(id1, list2));
199
            
200
            //should return sm1-sm4
201
            ObjectList list3 = cs.listObjects(token, d1, d5, null);
202
            assertTrue(list3.sizeObjectInfoList() == 4);
203
            ObjectInfo oi4 = list3.getObjectInfo(0);
204
            assertTrue(idInObjectList(id1, list3));
205
            assertTrue(idInObjectList(id2, list3));
206
            assertTrue(idInObjectList(id3, list3));
207
            assertTrue(idInObjectList(id4, list3));
208
            
209
            //should only return sm2 and sm4
210
            ObjectList list4 = cs.listObjects(token, d1, d5, of2);
211
            assertTrue(list4.sizeObjectInfoList() == 2);
212
            assertTrue(idInObjectList(id2, list4));
213
            assertTrue(idInObjectList(id4, list4));
214
            
215
            //should return all
216
            ObjectList list5 = cs.listObjects(token, d1, d6, null);
217
            assertTrue(list5.sizeObjectInfoList() == 5);
218
            assertTrue(idInObjectList(id1, list5));
219
            assertTrue(idInObjectList(id2, list5));
220
            assertTrue(idInObjectList(id3, list5));
221
            assertTrue(idInObjectList(id4, list5));
222
            assertTrue(idInObjectList(id5, list5));
223
            
224
            //should return 1, 3, 5
225
            ObjectList list6 = cs.listObjects(token, d1, d6, of1);
226
            assertTrue(list6.sizeObjectInfoList() == 3);
227
            assertTrue(idInObjectList(id1, list6));
228
            assertTrue(idInObjectList(id3, list6));
229
            assertTrue(idInObjectList(id5, list6));
230
            
231
	    }
232
	    catch(Exception e)
233
	    {
234
	        //e.printStackTrace();
235
	        fail("Error in listObjects: " + e.getMessage());
236
	    }
237
	}
238
	
239
	private boolean idInObjectList(Identifier id, ObjectList list)
240
	{
241
	    for(int i=0; i<list.sizeObjectInfoList(); i++)
242
	    {
243
	        ObjectInfo oi = list.getObjectInfo(i);
244
	        if(id.getValue().equals(oi.getIdentifier().getValue()))
245
	            return true;
246
	    }
247
	    return false;
248
	}
249
	
250
	/**
251
	 * public Identifier update(AuthToken token, Identifier guid, 
252
     *       InputStream object, Identifier obsoletedGuid, SystemMetadata sysmeta) 
253
     *         throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, 
254
     *           UnsupportedType, InsufficientResources, NotFound, InvalidSystemMetadata, 
255
     *           NotImplemented
256
	 */
257
	public void testUpdate()
258
	{
259
	    printTestHeader("testUpdate");
260
	    try
261
	    {
262
	        CrudService cs = CrudService.getInstance();
263
	        AuthToken token = getToken();
264
            //create a doc
265
            Identifier id = createDoc(token, getTestDoc());
266
            
267
            //get the doc and sysmetadata
268
            String gotDoc = getDoc(token, id);
269
            SystemMetadata sm = getSystemMetadata(token, id);
270
            
271
            //update the doc
272
            gotDoc = gotDoc.replaceAll("XXX", "YYY");
273
            Identifier newid = new Identifier();
274
            newid.setValue(generateDocumentId());
275
            StringBufferInputStream sbis = new StringBufferInputStream(gotDoc);
276
            SystemMetadata newsm = createSystemMetadata(newid, gotDoc);
277
            Identifier updatedid = cs.update(token, newid, sbis, id, newsm);
278
            
279
            //get doc - check that it matches update
280
            String newdoc = getDoc(token, newid);
281
            assertTrue(gotDoc.equals(newdoc));
282
            
283
            //get sysmeta - check that ids and other fields are updated
284
            SystemMetadata newnewsm = getSystemMetadata(token, id);
285
            assertTrue(newnewsm.getObsoletedBy(0).getValue().equals(newid.getValue()));
286
            
287
            //get the new sysmeta and make sure the obsoletes field is set
288
            SystemMetadata newnewnewsm = getSystemMetadata(token, newid);
289
            assertTrue(newnewnewsm.getObsolete(0).getValue().equals(id.getValue()));
290
        }
291
        catch(Exception e)
292
        {
293
            e.printStackTrace();
294
            fail("Error in testUpdate: " + e.getMessage());
295
        }
296
	}
297
	
298
	/**
299
	 * public SystemMetadata getSystemMetadata(AuthToken token, Identifier guid)
300
     *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
301
     *       InvalidRequest, NotImplemented
302
	 */
303
	public void testGetSystemMetadata()
304
	{
305
	    printTestHeader("testGetSystemMetadata");
306
	    try
307
	    {
308
            CrudService cs = CrudService.getInstance();
309
            AuthToken token = getToken();
310
            //run create
311
            Identifier id = createDoc(token, getTestDoc());
312
            //get the systemMetadata and make sure it is the correct object for this testDoc
313
            SystemMetadata sm = getSystemMetadata(token, id);
314
            assertTrue(sm.getIdentifier().getValue().equals(id.getValue()));
315
            assertTrue(sm.getChecksum().getValue().equals(checksum(getTestDoc())));
316
            
317
            try
318
            {
319
                Identifier fakeid = new Identifier();
320
                fakeid.setValue("somethingfake.234234");
321
                getSystemMetadata(token, fakeid);
322
                fail("getSystemMetadata should have thrown an exception.");
323
            }
324
            catch(Exception e)
325
            {
326
                assertTrue(true);
327
            }
328
        }
329
        catch(Exception e)
330
        {
331
            e.printStackTrace();
332
            fail("Error testing system metadata: " + e.getMessage());
333
        }
334
	}
335
	
336
	/**
337
	 * create(AuthToken token, Identifier guid, InputStream object, SystemMetadata sysmeta) 
338
     *   throws InvalidToken, ServiceFailure, NotAuthorized, IdentifierNotUnique, UnsupportedType, 
339
     *       InsufficientResources, InvalidSystemMetadata, NotImplemented
340
     *
341
     * public InputStream get(AuthToken token, Identifier guid)
342
     *       throws InvalidToken, ServiceFailure, NotAuthorized, NotFound, 
343
     *       NotImplemented
344
	 */
345
	public void testCreateAndGet()
346
	{
347
	    printTestHeader("testCreateAndGet");
348
	    try
349
	    {
350
	        CrudService cs = CrudService.getInstance();
351
	        AuthToken token = getToken();
352
	        //run create
353
	        Identifier id = createDoc(token, getTestDoc());
354
	        //make these docs public for debugging purposes.
355
	        makeDocPublic(id, true);
356
            //compare the docs
357
            String gotDoc = getDoc(token, id);
358
            assertTrue(gotDoc.trim().equals(getTestDoc().trim()));
359
            
360
            try
361
            {
362
                Identifier fakeid = new Identifier();
363
                fakeid.setValue("somethingfake.234234");
364
                getDoc(token, fakeid);
365
                fail("testCreateAndGet should have thrown an exception.");
366
            }
367
            catch(Exception e)
368
            {
369
                assertTrue(true);
370
            }
371
        }
372
        catch(Exception e)
373
        {
374
            e.printStackTrace();
375
            fail("Error in testCreate: " + e.getMessage());
376
        }
377
	}
378

    
379
	/**
380
	 * getInstance()
381
	 */
382
	public void testSingletonAccessor()
383
	{
384
	    printTestHeader("testSingletonAccessor");
385
	    CrudService cs = CrudService.getInstance();
386
	    assertNotNull(cs);
387
	}
388
	
389
	/**
390
	 * Run an initial test that always passes to check that the test harness is
391
	 * working.
392
	 */
393
	public void initialize() 
394
	{
395
	    printTestHeader("initialize");
396
		assertTrue(1 == 1);
397
	}
398
	
399
	/**
400
	 * return the systemMetadata object for id
401
	 */
402
	private SystemMetadata getSystemMetadata(AuthToken token, Identifier id)
403
	  throws Exception
404
	{
405
	    CrudService cs = CrudService.getInstance();
406
	    return cs.getSystemMetadata(token, id);
407
	}
408
	
409
	/**
410
	 * get a doc from metacat using CrudService.get()
411
	 */
412
	private String getDoc(AuthToken token, Identifier id)
413
	  throws Exception
414
	{
415
	    CrudService cs = CrudService.getInstance();
416
	    //try to get the same doc then compare them
417
        InputStream gotDocStream = cs.get(token, id);
418
        StringBuffer sb = new StringBuffer();
419
        byte[] b = new byte[1024];
420
        int numread = gotDocStream.read(b, 0, 1024);
421
        while(numread != -1)
422
        {
423
            sb.append(new String(b, 0, numread));
424
            numread = gotDocStream.read(b, 0, 1024);
425
        }
426
        return sb.toString();
427
	}
428
	
429
	/**
430
	 * return a test document
431
	 */
432
	private String getTestDoc()
433
	{
434
	    return "<?xml version=\"1.0\"?><test><somecontent>This is some content XXX</somecontent></test>\n";
435
	}
436
	
437
	/**
438
	 * authenticate and return a token
439
	 */
440
	private AuthToken getToken()
441
	  throws Exception
442
	{
443
	    CrudService cs = CrudService.getInstance();
444
        //login and get a sessionid
445
        MetacatRestClient restClient = new MetacatRestClient(cs.getContextUrl());
446
        String username = PropertyService.getProperty("test.mcUser");
447
        String password = PropertyService.getProperty("test.mcPassword");
448
        String response = restClient.login(username, password);
449
        String sessionid = restClient.getSessionId();
450
        SessionService sessionService = SessionService.getInstance();
451
        sessionService.registerSession(new SessionData(sessionid, username, new String[0], password, "CrudServiceLogin"));
452
        AuthToken token = new AuthToken(sessionid);
453
        return token;
454
	}
455
	
456
	/**
457
	 * create a doc using CrudService.create() and return its id
458
	 */
459
	private Identifier createDoc(AuthToken token, String testDoc) throws Exception
460
	{
461
	    return createDoc(token, testDoc, ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
462
	}
463
	
464
	/**
465
	 * create a doc using CrudService.create() and return its id
466
	 */
467
	private Identifier createDoc(AuthToken token, String testDoc, ObjectFormat format) throws Exception
468
	{
469
	    Identifier id;
470
        CrudService cs = CrudService.getInstance();
471
        
472
        id = new Identifier();
473
        String docid = generateDocumentId();
474
        id.setValue(docid);
475
        
476
        //create the system metadata then run the create method
477
        StringBufferInputStream sbis = new StringBufferInputStream(testDoc);
478
        SystemMetadata sm = createSystemMetadata(id, testDoc, format);
479
        //create the doc
480
        cs.create(token, id, sbis, sm);
481
        return id;
482
	}
483
	
484
	/**
485
	 * create a generic SystemMetadata object for testing
486
	 */
487
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc)
488
	  throws Exception
489
	{
490
	    return createSystemMetadata(id, testDoc, 
491
	            ObjectFormat.convert("eml://ecoinformatics.org/eml-2.1.0"));
492
	}
493
	
494
	/**
495
	 * create system metadata with a specified id, doc and format
496
	 */
497
	private SystemMetadata createSystemMetadata(Identifier id, String testDoc, ObjectFormat format)
498
	  throws Exception
499
	{
500
	    SystemMetadata sm = new SystemMetadata();
501
        //set the id
502
        sm.setIdentifier(id);
503
        sm.setObjectFormat(format);
504
        //create the checksum
505
        String checksumS = checksum(testDoc);
506
        ChecksumAlgorithm ca = ChecksumAlgorithm.convert("MD5");
507
        Checksum checksum = new Checksum();
508
        checksum.setValue(checksumS);
509
        checksum.setAlgorithm(ca);
510
        sm.setChecksum(checksum);
511
        //set the size
512
        sm.setSize(testDoc.getBytes().length);
513
        //submitter
514
        Principal p = new Principal();
515
        p.setValue("joe");
516
        sm.setSubmitter(p);
517
        sm.setRightsHolder(p);
518
        sm.setDateUploaded(new Date());
519
        sm.setDateSysMetadataModified(new Date());
520
        NodeReference nr = new NodeReference();
521
        nr.setValue("metacat");
522
        sm.setOriginMemberNode(nr);
523
        sm.setAuthoritativeMemberNode(nr);
524
        return sm;
525
	}
526
	
527
	/**
528
	 *  make a document public in metacat by inserting an access document
529
	 * @param id
530
	 */
531
	private void makeDocPublic(Identifier id, boolean systemMetadataToo)
532
	  throws Exception
533
	{
534
	    CrudService cs = CrudService.getInstance();
535
	    IdentifierManager im = IdentifierManager.getInstance();
536
	    cs.setAccess(getToken(), id, "public", "read", "allow", "allowFirst");
537
	    if(systemMetadataToo)
538
	    {
539
	        String smidS = im.getSystemMetadataId(id.getValue());
540
	        Identifier smid = new Identifier();
541
	        smid.setValue(smidS);
542
	        cs.setAccess(getToken(), smid, "public", "read", "allow", "allowFirst");
543
	    }
544
	}
545
	
546
	/**
547
	 * print a header to start each test
548
	 */
549
	private void printTestHeader(String testName)
550
	{
551
	    System.out.println();
552
	    System.out.println("********************************** " + testName + " **********************************");
553
	}
554
  
555
	/**
556
	 * produce an md5 checksum for item
557
	 */
558
	private String checksum(String item)
559
	  throws Exception
560
	{
561
        StringBufferInputStream fis =  new StringBufferInputStream(item);
562
        
563
        byte[] buffer = new byte[1024];
564
        MessageDigest complete = MessageDigest.getInstance("MD5");
565
        int numRead;
566
        
567
        do 
568
        {
569
          numRead = fis.read(buffer);
570
          if (numRead > 0) 
571
          {
572
            complete.update(buffer, 0, numRead);
573
          }
574
        } while (numRead != -1);
575
        
576
        
577
        return getHex(complete.digest());
578
	}
579
	
580
	/**
581
	 * convert a byte array to a hex string
582
	 */
583
	private static String getHex( byte [] raw ) 
584
	{
585
	    final String HEXES = "0123456789ABCDEF";
586
        if ( raw == null ) {
587
          return null;
588
        }
589
        final StringBuilder hex = new StringBuilder( 2 * raw.length );
590
        for ( final byte b : raw ) {
591
          hex.append(HEXES.charAt((b & 0xF0) >> 4))
592
             .append(HEXES.charAt((b & 0x0F)));
593
        }
594
        return hex.toString();
595
    }
596
}
(1-1/2)