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
 *
6
 *   '$Author: jones $'
7
 *     '$Date: 2010-02-03 17:58:12 -0900 (Wed, 03 Feb 2010) $'
8
 * '$Revision: 5211 $'
9
 *
10
 * This program is free software; you can redistribute it and/or modify
11
 * it under the terms of the GNU General Public License as published by
12
 * the Free Software Foundation; either version 2 of the License, or
13
 * (at your option) any later version.
14
 *
15
 * This program is distributed in the hope that it will be useful,
16
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18
 * GNU General Public License for more details.
19
 *
20
 * You should have received a copy of the GNU General Public License
21
 * along with this program; if not, write to the Free Software
22
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23
 */
24

    
25
package edu.ucsb.nceas.metacat;
26

    
27
import java.math.BigInteger;
28
import java.sql.PreparedStatement;
29
import java.sql.ResultSet;
30
import java.sql.SQLException;
31
import java.sql.Timestamp;
32
import java.util.ArrayList;
33
import java.util.Date;
34
import java.util.Hashtable;
35
import java.util.List;
36
import java.util.Vector;
37

    
38
import org.apache.log4j.Logger;
39
import org.dataone.client.ObjectFormatCache;
40
import org.dataone.service.exceptions.NotFound;
41
import org.dataone.service.types.v1.AccessPolicy;
42
import org.dataone.service.types.v1.AccessRule;
43
import org.dataone.service.types.v1.Checksum;
44
import org.dataone.service.types.v1.Identifier;
45
import org.dataone.service.types.v1.NodeReference;
46
import org.dataone.service.types.v1.ObjectFormatIdentifier;
47
import org.dataone.service.types.v1.ObjectInfo;
48
import org.dataone.service.types.v1.ObjectList;
49
import org.dataone.service.types.v1.Permission;
50
import org.dataone.service.types.v1.Replica;
51
import org.dataone.service.types.v1.ReplicationPolicy;
52
import org.dataone.service.types.v1.ReplicationStatus;
53
import org.dataone.service.types.v1.Subject;
54
import org.dataone.service.types.v1.SystemMetadata;
55

    
56
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
57
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
58
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
59
import edu.ucsb.nceas.metacat.database.DBConnection;
60
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
61
import edu.ucsb.nceas.metacat.properties.PropertyService;
62
import edu.ucsb.nceas.metacat.shared.AccessException;
63
import edu.ucsb.nceas.metacat.shared.ServiceException;
64
import edu.ucsb.nceas.metacat.util.DocumentUtil;
65
import edu.ucsb.nceas.utilities.PropertyNotFoundException;
66

    
67
/**
68
 * Manage the relationship between Metacat local identifiers (LocalIDs) that are
69
 * codified as the (docid, rev) pair with globally unique string identifiers
70
 * (GUIDs) that are opaque strings.  This class provides methods to manage these
71
 * identifiers, and to search for and look up LocalIDs based on their GUID and
72
 * vice versa. IdentifierManager is a singleton.
73
 * 
74
 * @author Matthew Jones
75
 */
76
public class IdentifierManager {
77
    
78
    public static final String TYPE_SYSTEM_METADATA = "systemmetadata";
79
    public static final String TYPE_IDENTIFIER = "identifier";
80
  
81
    /**
82
     * The single instance of the manager that is always returned.
83
     */
84
    private static IdentifierManager self = null;
85
    private Logger logMetacat = Logger.getLogger(IdentifierManager.class);
86

    
87
    /**
88
     * A private constructor that initializes the class when getInstance() is
89
     * called.
90
     */
91
    private IdentifierManager() {}
92

    
93
    /**
94
     * Return the single instance of the manager after initializing it if it
95
     * wasn't previously initialized.
96
     * 
97
     * @return the single IdentifierManager instance
98
     */
99
    public static IdentifierManager getInstance()
100
    {
101
        if (self == null) {
102
            self = new IdentifierManager();
103
        }
104
        return self;
105
    }
106
    
107
    public SystemMetadata asSystemMetadata(Date dateUploaded, String rightsHolder,
108
            String checksum, String checksumAlgorithm, String originMemberNode,
109
            String authoritativeMemberNode, Date dateModified, String submitter, 
110
            String guid, String fmtidStr, BigInteger size, BigInteger serialVersion) {
111
        SystemMetadata sysMeta = new SystemMetadata();
112

    
113
        Identifier sysMetaId = new Identifier();
114
        sysMetaId.setValue(guid);
115
        sysMeta.setIdentifier(sysMetaId);
116
        sysMeta.setDateUploaded(dateUploaded);
117
        Subject rightsHolderSubject = new Subject();
118
        rightsHolderSubject.setValue(rightsHolder);
119
        sysMeta.setRightsHolder(rightsHolderSubject);
120
        Checksum checksumObject = new Checksum();
121
        checksumObject.setValue(checksum);
122
        checksumObject.setAlgorithm(checksumAlgorithm);
123
        sysMeta.setChecksum(checksumObject);
124
        NodeReference omn = new NodeReference();
125
        omn.setValue(originMemberNode);
126
        sysMeta.setOriginMemberNode(omn);
127
        NodeReference amn = new NodeReference();
128
        amn.setValue(authoritativeMemberNode);
129
        sysMeta.setAuthoritativeMemberNode(amn);
130
        sysMeta.setDateSysMetadataModified(dateModified);
131
        Subject submitterSubject = new Subject();
132
        submitterSubject.setValue(submitter);
133
        sysMeta.setSubmitter(submitterSubject);
134
        try {
135
        	ObjectFormatIdentifier fmtid = 
136
        		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFormatId();
137
        	sysMeta.setFormatId(fmtid);
138
        } catch (NotFound nfe) {
139
          logMetacat.error("The objectFormat " + fmtidStr +
140
          	" is not registered. Setting the default format id.");
141
          ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
142
          fmtid.setValue("application/octet-stream");
143
          sysMeta.setFormatId(fmtid);
144
        }
145
        sysMeta.setSize(size);
146
        sysMeta.setSerialVersion(serialVersion);
147
        
148
        return sysMeta;
149
    }
150
    
151
    /**
152
     * return a hash of all of the info that is in the systemmetadata table
153
     * @param localId
154
     * @return
155
     */
156
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
157
    throws McdbDocNotFoundException
158
    {
159
        try
160
        {
161
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
162
            localId = acc.getDocid();
163
        }
164
        catch(Exception e)
165
        {
166
            //do nothing. just try the localId as it is
167
        }
168
        Hashtable<String, String> h = new Hashtable<String, String>();
169
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
170
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
171
          "from systemmetadata where docid = ?";
172
        DBConnection dbConn = null;
173
        int serialNumber = -1;
174
        try 
175
        {
176
            // Get a database connection from the pool
177
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
178
            serialNumber = dbConn.getCheckOutSerialNumber();
179

    
180
            // Execute the insert statement
181
            PreparedStatement stmt = dbConn.prepareStatement(sql);
182
            stmt.setString(1, localId);
183
            ResultSet rs = stmt.executeQuery();
184
            if (rs.next()) 
185
            {
186
                String guid = rs.getString(1);
187
                Timestamp dateUploaded = rs.getTimestamp(2);
188
                String rightsHolder = rs.getString(3);
189
                String checksum = rs.getString(4);
190
                String checksumAlgorithm = rs.getString(5);
191
                String originMemberNode = rs.getString(6);
192
                String authoritativeMemberNode = rs.getString(7);
193
                Timestamp dateModified = rs.getTimestamp(8);
194
                String submitter = rs.getString(9);
195
                String objectFormat = rs.getString(10);
196
                long size = new Long(rs.getString(11)).longValue();
197
                
198
                h.put("guid", guid);
199
                h.put("date_uploaded", new Long(dateUploaded.getTime()).toString());
200
                h.put("rights_holder", rightsHolder);
201
                h.put("checksum", checksum);
202
                h.put("checksum_algorithm", checksumAlgorithm);
203
                h.put("origin_member_node", originMemberNode);
204
                h.put("authoritative_member_node", authoritativeMemberNode);
205
                h.put("date_modified", new Long(dateModified.getTime()).toString());
206
                h.put("submitter", submitter);
207
                h.put("object_format", objectFormat);
208
                h.put("size", new Long(size).toString());
209
                
210
                stmt.close();
211
            } 
212
            else
213
            {
214
                stmt.close();
215
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
216
                throw new McdbDocNotFoundException("2Could not find document " + localId);
217
            }
218
            
219
        } 
220
        catch (SQLException e) 
221
        {
222
            e.printStackTrace();
223
            logMetacat.error("Error while getting system metadata info for localid " + localId + " : "  
224
                    + e.getMessage());
225
        } 
226
        finally 
227
        {
228
            // Return database connection to the pool
229
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
230
        }
231
        return h;
232
    }
233
    
234
    /**
235
     * return a hash of all of the info that is in the systemmetadata table
236
     * @param guid
237
     * @return
238
     * @throws McdbDocNotFoundException 
239
     */
240
    public SystemMetadata getSystemMetadata(String guid)
241
    	throws McdbDocNotFoundException
242
    {
243
        
244
        SystemMetadata sysMeta = new SystemMetadata();
245
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
246
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size, " +
247
          "replication_allowed, number_replicas, obsoletes, obsoleted_by, serial_version " +
248
          "from systemmetadata where guid = ?";
249
        DBConnection dbConn = null;
250
        int serialNumber = -1;
251
        Boolean replicationAllowed = new Boolean(false);
252
        BigInteger numberOfReplicas = new BigInteger("-1");
253
        BigInteger serialVersion = new BigInteger("-1");
254

    
255
        try 
256
        {
257
            // Get a database connection from the pool
258
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadata");
259
            serialNumber = dbConn.getCheckOutSerialNumber();
260

    
261
            // Execute the statement
262
            PreparedStatement stmt = dbConn.prepareStatement(sql);
263
            stmt.setString(1, guid);
264
            ResultSet rs = stmt.executeQuery();
265
            if (rs.next()) 
266
            {
267
                Timestamp dateUploaded = rs.getTimestamp(2);
268
                String rightsHolder = rs.getString(3);
269
                String checksum = rs.getString(4);
270
                String checksumAlgorithm = rs.getString(5);
271
                String originMemberNode = rs.getString(6);
272
                String authoritativeMemberNode = rs.getString(7);
273
                Timestamp dateModified = rs.getTimestamp(8);
274
                String submitter = rs.getString(9);
275
                String fmtidStr = rs.getString(10);
276
                BigInteger size = new BigInteger(rs.getString(11));
277
                replicationAllowed = new Boolean(rs.getBoolean(12));
278
                numberOfReplicas = new BigInteger(rs.getString(13));
279
                String obsoletes = rs.getString(14);
280
                String obsoletedBy = rs.getString(15);
281
                serialVersion = new BigInteger(rs.getString(16));
282

    
283

    
284
                Identifier sysMetaId = new Identifier();
285
                sysMetaId.setValue(guid);
286
                sysMeta.setIdentifier(sysMetaId);
287
                sysMeta.setSerialVersion(serialVersion);
288
                sysMeta.setDateUploaded(dateUploaded);
289
                Subject rightsHolderSubject = new Subject();
290
                rightsHolderSubject.setValue(rightsHolder);
291
                sysMeta.setRightsHolder(rightsHolderSubject);
292
                Checksum checksumObject = new Checksum();
293
                checksumObject.setValue(checksum);
294
                checksumObject.setAlgorithm(checksumAlgorithm);
295
                sysMeta.setChecksum(checksumObject);
296
                if (originMemberNode != null) {
297
	                NodeReference omn = new NodeReference();
298
	                omn.setValue(originMemberNode);
299
	                sysMeta.setOriginMemberNode(omn);
300
                }
301
                if (authoritativeMemberNode != null) {
302
	                NodeReference amn = new NodeReference();
303
	                amn.setValue(authoritativeMemberNode);
304
	                sysMeta.setAuthoritativeMemberNode(amn);
305
                }
306
                sysMeta.setDateSysMetadataModified(dateModified);
307
                Subject submitterSubject = new Subject();
308
                submitterSubject.setValue(submitter);
309
                sysMeta.setSubmitter(submitterSubject);
310
                try {
311
                	ObjectFormatIdentifier fmtid = 
312
                		ObjectFormatCache.getInstance().getFormat(fmtidStr).getFormatId();
313
                	sysMeta.setFormatId(fmtid);
314
                } catch (NotFound nfe) {
315
                  logMetacat.error("The objectFormat " + fmtidStr +
316
                  	" is not registered. Setting the default format id.");
317
                  ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
318
                  fmtid.setValue("application/octet-stream");
319
                  sysMeta.setFormatId(fmtid);
320
                }
321
                sysMeta.setSize(size);
322
                if (obsoletes != null) {
323
	                Identifier obsoletesId = new Identifier();
324
	                obsoletesId.setValue(obsoletes);
325
	                sysMeta.setObsoletes(obsoletesId);
326
                }
327
                if (obsoletedBy != null) {
328
		            Identifier obsoletedById = new Identifier();
329
		            obsoletedById.setValue(obsoletedBy);
330
		            sysMeta.setObsoletedBy(obsoletedById);
331
                }
332
                stmt.close();
333
            } 
334
            else
335
            {
336
                stmt.close();
337
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
338
                throw new McdbDocNotFoundException("Could not find " + guid);
339
            }
340
            
341
        } 
342
        catch (SQLException e) 
343
        {
344
            e.printStackTrace();
345
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
346
                    + e.getMessage());
347
        } 
348
        finally 
349
        {
350
            // Return database connection to the pool
351
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
352
        }
353

    
354
        // populate the replication policy
355
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
356
        if ( numberOfReplicas != null  && numberOfReplicas.intValue() != -1 ) {
357
            replicationPolicy.setNumberReplicas(numberOfReplicas.intValue());
358
            
359
        }
360
        
361
        if ( replicationAllowed != null ) {
362
            replicationPolicy.setReplicationAllowed(replicationAllowed);
363
            
364
        }
365
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
366
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
367
		    sysMeta.setReplicationPolicy(replicationPolicy);
368
		
369
		    // look up replication status
370
		    sysMeta.setReplicaList(getReplicationStatus(guid));
371
		
372
		    // look up access policy
373
		    try {
374
		    	sysMeta.setAccessPolicy(getAccessPolicy(guid));
375
		    } catch (AccessException e) {
376
		    	throw new McdbDocNotFoundException(e);
377
		    }
378
        
379
        return sysMeta;
380
    }
381
    
382
    
383
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
384
		throws McdbDocNotFoundException {
385
		
386
		List<NodeReference> nodes = new ArrayList<NodeReference>();
387
		String sql = "select guid, policy, member_node " +
388
			"from systemMetadataReplicationPolicy where guid = ? and policy = ?";
389
	    DBConnection dbConn = null;
390
	    int serialNumber = -1;
391
	    try {
392
	        // Get a database connection from the pool
393
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
394
	        serialNumber = dbConn.getCheckOutSerialNumber();
395
	
396
	        // Execute the statement
397
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
398
	        stmt.setString(1, guid);
399
	        stmt.setString(2, policy);
400
	        ResultSet rs = stmt.executeQuery();
401
	        while (rs.next()) 
402
	        {
403
	            String memberNode = rs.getString(3);
404
	            NodeReference node = new NodeReference();
405
	            node.setValue(memberNode);
406
	            nodes.add(node);
407
	        
408
	        } 
409
	        stmt.close();
410
	        
411
	    } catch (SQLException e) {
412
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
413
	    } 
414
	    finally {
415
	        // Return database connection to the pool
416
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
417
	    }
418
	    
419
	    return nodes;
420
	}
421
    
422
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
423
		
424
		List<Replica> replicas = new ArrayList<Replica>();
425
		String sql = "select guid, member_node, status, date_verified " +
426
			"from systemMetadataReplicationStatus where guid = ?";
427
	    DBConnection dbConn = null;
428
	    int serialNumber = -1;
429
	    try {
430
	        // Get a database connection from the pool
431
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
432
	        serialNumber = dbConn.getCheckOutSerialNumber();
433
	
434
	        // Execute the statement
435
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
436
	        stmt.setString(1, guid);
437
	        ResultSet rs = stmt.executeQuery();
438
	        while (rs.next()) 
439
	        {
440
	            String memberNode = rs.getString(2);
441
	            String status = rs.getString(3);
442
	            java.sql.Date verified = rs.getDate(4);
443
	            
444
	            Replica replica = new Replica();	            
445
	            NodeReference node = new NodeReference();
446
	            node.setValue(memberNode);
447
	            replica.setReplicaMemberNode(node);
448
	            replica.setReplicationStatus(ReplicationStatus.valueOf(status));
449
	            replica.setReplicaVerified(new Date(verified.getTime()));
450
	            replicas.add(replica);
451
	        } 
452
	        stmt.close();
453
	        
454
	    } catch (SQLException e) {
455
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
456
	    } 
457
	    finally {
458
	        // Return database connection to the pool
459
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
460
	    }
461
	    
462
	    return replicas;
463
	}
464
    
465
    
466
    /**
467
     * return the newest rev for a given localId
468
     * @param localId
469
     * @return
470
     */
471
    public int getLatestRevForLocalId(String localId)
472
        throws McdbDocNotFoundException
473
    {
474
        try
475
        {
476
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
477
            localId = acc.getDocid();
478
        }
479
        catch(Exception e)
480
        {
481
            //do nothing. just try the localId as it is
482
        }
483
        int rev = 0;
484
        String sql = "select rev from xml_documents where docid like ? ";
485
        DBConnection dbConn = null;
486
        int serialNumber = -1;
487
        try 
488
        {
489
            // Get a database connection from the pool
490
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
491
            serialNumber = dbConn.getCheckOutSerialNumber();
492

    
493
            // Execute the insert statement
494
            PreparedStatement stmt = dbConn.prepareStatement(sql);
495
            stmt.setString(1, localId);
496
            ResultSet rs = stmt.executeQuery();
497
            if (rs.next()) 
498
            {
499
                rev = rs.getInt(1);
500
                stmt.close();
501
            } 
502
            else
503
            {
504
                stmt.close();
505
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
506
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
507
            }
508
        } 
509
        catch (SQLException e) 
510
        {
511
            logMetacat.error("Error while looking up the guid: " 
512
                    + e.getMessage());
513
        } 
514
        finally 
515
        {
516
            // Return database connection to the pool
517
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
518
        }
519
        return rev;
520
    }
521
    
522
    /**
523
     * return all local ids in the object store that do not have associated
524
     * system metadata
525
     */
526
    public List<String> getLocalIdsWithNoSystemMetadata(boolean includeRevisions)
527
    {
528
        Vector<String> ids = new Vector<String>();
529
        String sql = "select docid, rev from xml_documents " +
530
        		"where docid not in " +
531
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
532
        
533
        String revisionSql = "select docid, revisionid from xml_revisions " +
534
				"where docid not in " +
535
				"(select docid from identifier where guid in (select guid from systemmetadata)))";
536
        
537
        if (includeRevisions) {
538
        	sql = sql + " UNION ALL " + revisionSql;
539
        }
540
        
541
        DBConnection dbConn = null;
542
        int serialNumber = -1;
543
        try 
544
        {
545
            // Get a database connection from the pool
546
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
547
            serialNumber = dbConn.getCheckOutSerialNumber();
548

    
549
            // Execute the insert statement
550
            PreparedStatement stmt = dbConn.prepareStatement(sql);
551
            ResultSet rs = stmt.executeQuery();
552
            while (rs.next()) 
553
            {
554
                String localid = rs.getString(1);
555
                String rev = rs.getString(2);
556
                localid += "." + rev;
557
                logMetacat.debug("id to add SM for: " + localid);
558
                ids.add(localid);
559
            } 
560
            stmt.close();
561
        } 
562
        catch (SQLException e) 
563
        {
564
            logMetacat.error("Error while looking up the guid: " 
565
                    + e.getMessage());
566
        } 
567
        finally 
568
        {
569
            // Return database connection to the pool
570
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
571
        }
572
        
573
        return ids;
574
    }
575
    
576
    /**
577
     * return a listing of all local ids in the object store
578
     * @return a list of all local ids in metacat
579
     */
580
    public List<String> getAllLocalIds()
581
    // seems to be an unnecessary and restrictive throw -rnahf 13-Sep-2011
582
    //    throws Exception
583
    {
584
        Vector<String> ids = new Vector<String>();
585
        String sql = "select docid from xml_documents";
586
        DBConnection dbConn = null;
587
        int serialNumber = -1;
588
        try 
589
        {
590
            // Get a database connection from the pool
591
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
592
            serialNumber = dbConn.getCheckOutSerialNumber();
593

    
594
            // Execute the insert statement
595
            PreparedStatement stmt = dbConn.prepareStatement(sql);
596
            ResultSet rs = stmt.executeQuery();
597
            while (rs.next()) 
598
            {
599
                String localid = rs.getString(1);
600
                ids.add(localid);
601
            } 
602
            stmt.close();
603
        } 
604
        catch (SQLException e) 
605
        {
606
            logMetacat.error("Error while looking up the guid: " 
607
                    + e.getMessage());
608
        } 
609
        finally 
610
        {
611
            // Return database connection to the pool
612
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
613
        }
614
        return ids;
615
    }
616
    
617
    
618
    /**
619
     * return a listing of all guids in the object store
620
     * @return a list of all GUIDs in metacat
621
     */
622
    public List<String> getAllGUIDs()
623
    {
624
        Vector<String> guids = new Vector<String>();
625
        String sql = "select guid from identifier";
626
        DBConnection dbConn = null;
627
        int serialNumber = -1;
628
        try 
629
        {
630
            // Get a database connection from the pool
631
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllGUIDs");
632
            serialNumber = dbConn.getCheckOutSerialNumber();
633

    
634
            // Execute the insert statement
635
            PreparedStatement stmt = dbConn.prepareStatement(sql);
636
            ResultSet rs = stmt.executeQuery();
637
            while (rs.next()) 
638
            {
639
                String guid = rs.getString(1);
640
                guids.add(guid);
641
            } 
642
            stmt.close();
643
        } 
644
        catch (SQLException e) 
645
        {
646
            logMetacat.error("Error while retrieving the guid: " 
647
                    + e.getMessage());
648
        } 
649
        finally 
650
        {
651
            // Return database connection to the pool
652
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
653
        }
654
        return guids;
655
    }
656
    
657
    
658
    
659
    /**
660
     * returns a list of system metadata-only guids since the given date
661
     * @return a list of system ids in metacat that do not correspond to objects
662
     * TODO: need to check which server they are on
663
     */
664
    public List<String> getUpdatedSystemMetadataIds(Date since)
665
       throws Exception
666
    {
667
        List<String> ids = new Vector<String>();
668
        String sql = 
669
        	"select guid from " + TYPE_SYSTEM_METADATA +
670
        	" where guid not in " +
671
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
672
        	" and date_modified > ?";
673
        DBConnection dbConn = null;
674
        int serialNumber = -1;
675
        try 
676
        {
677
            // Get a database connection from the pool
678
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
679
            serialNumber = dbConn.getCheckOutSerialNumber();
680

    
681
            // Execute the insert statement
682
            PreparedStatement stmt = dbConn.prepareStatement(sql);
683
            stmt.setDate(1, new java.sql.Date(since.getTime()));
684
            ResultSet rs = stmt.executeQuery();
685
            while (rs.next()) 
686
            {
687
                String guid = rs.getString(1);
688
                ids.add(guid);
689
            } 
690
            stmt.close();
691
        } 
692
        catch (SQLException e) 
693
        {
694
            logMetacat.error("Error while looking up the updated guids: " 
695
                    + e.getMessage());
696
        } 
697
        finally 
698
        {
699
            // Return database connection to the pool
700
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
701
        }
702
        return ids;
703
    }
704
    
705
    /**
706
     * returns a list of system metadata-only guids since the given date
707
     * @return a list of system ids in metacat that do not correspond to objects
708
     * TODO: need to check which server they are on
709
     */
710
    public Date getLastModifiedDate() throws Exception {
711
        Date maxDate = null;
712

    
713
        List<String> ids = new Vector<String>();
714
        String sql = 
715
        	"select max(date_modified) from " + TYPE_SYSTEM_METADATA;
716
        DBConnection dbConn = null;
717
        int serialNumber = -1;
718
        try 
719
        {
720
            // Get a database connection from the pool
721
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLastModifiedDate");
722
            serialNumber = dbConn.getCheckOutSerialNumber();
723

    
724
            // Execute the insert statement
725
            PreparedStatement stmt = dbConn.prepareStatement(sql);
726
            ResultSet rs = stmt.executeQuery();
727
            if (rs.next()) {
728
            	maxDate = rs.getDate(1);
729
            } 
730
            stmt.close();
731
        } 
732
        catch (SQLException e) 
733
        {
734
            logMetacat.error("Error while looking up the latest update date: " 
735
                    + e.getMessage());
736
        } 
737
        finally 
738
        {
739
            // Return database connection to the pool
740
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
741
        }
742
        return maxDate;
743
    }
744

    
745
    
746
    /**
747
     * Determine if an identifier exists already, returning true if so.
748
     * 
749
     * @param guid the global identifier to look up
750
     * @return boolean true if the identifier exists
751
     */
752
    public boolean identifierExists(String guid)
753
    {
754
        boolean idExists = false;
755
        try {
756
            String id = getLocalId(guid);
757
            if (id != null) {
758
                idExists = true;
759
            }
760
        } catch (McdbDocNotFoundException e) {
761
        	// try system metadata only
762
        	try {
763
        		idExists = systemMetadataExists(guid);
764
            } catch (Exception e2) {
765
            	idExists = false;
766
            }
767
        }
768
        return idExists;
769
    }
770
    
771
    /**
772
     * 
773
     * @param guid
774
     * @param rev
775
     * @return
776
     */
777
    public String generateLocalId(String guid, int rev)
778
    {
779
        return generateLocalId(guid, rev, false);
780
    }
781

    
782
    /**
783
     * Given a global identifier (guid), create a suitable local identifier that
784
     * follows Metacat's docid semantics and format (scope.id.rev), and create
785
     * a mapping between these two identifiers.  This effectively reserves both
786
     * the global and the local identifier, as they will now be present in the
787
     * identifier mapping table.  If the incoming guid has the syntax of a
788
     * Metacat docid (scope.id.rev), then simply use it.
789
     * 
790
     * @param guid the global string identifier
791
     * @param rev the revision number to be used in the localId
792
     * @return String containing the localId to be used for Metacat operations
793
     */
794
    public String generateLocalId(String guid, int rev, boolean isSystemMetadata) 
795
    {
796
        String localId = "";
797
        boolean conformsToDocidFormat = false;
798
        
799
        // Check if the guid passed in is already in docid (scope.id.rev) format
800
        try {
801
            AccessionNumber acc = new AccessionNumber(guid, "NONE");
802
            if (new Integer(acc.getRev()).intValue() > 0) {
803
                conformsToDocidFormat = true;
804
            }
805
        } catch (NumberFormatException e) {
806
            // No action needed, simply detecting invalid AccessionNumbers
807
        } catch (AccessionNumberException e) {
808
            // No action needed, simply detecting invalid AccessionNumbers
809
        } catch (SQLException e) {
810
            // No action needed, simply detecting invalid AccessionNumbers
811
        }
812
        
813
        if (conformsToDocidFormat) {
814
            // if it conforms, use it for both guid and localId
815
            localId = guid;
816
        } else {
817
            // if not, then generate a new unique localId
818
            localId = DocumentUtil.generateDocumentId(rev);
819
        }
820
        
821
        // Register this new pair in the identifier mapping table
822
        logMetacat.debug("creating mapping in generateLocalId");
823
        if(!isSystemMetadata)
824
        { //don't do this if we're generating for system metadata
825
            createMapping(guid, localId);
826
        }
827
        
828
        return localId;
829
    }
830
    
831
    /**
832
     * given a local identifer, look up the guid.  Throw McdbDocNotFoundException
833
     * if the docid, rev is not found in the identifiers or systemmetadata tables
834
     *
835
     * @param docid the docid to look up
836
     * @param rev the revision of the docid to look up
837
     * @return String containing the mapped guid
838
     * @throws McdbDocNotFoundException if the docid, rev is not found
839
     */
840
    public String getGUID(String docid, int rev)
841
      throws McdbDocNotFoundException
842
    {
843
        logMetacat.debug("getting guid for " + docid);
844
        String query = "select guid from identifier where docid = ? and rev = ?";
845
        String guid = null;
846
        
847
        DBConnection dbConn = null;
848
        int serialNumber = -1;
849
        try {
850
            // Get a database connection from the pool
851
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getGUID");
852
            serialNumber = dbConn.getCheckOutSerialNumber();
853
            
854
            // Execute the insert statement
855
            PreparedStatement stmt = dbConn.prepareStatement(query);
856
            stmt.setString(1, docid);
857
            stmt.setInt(2, rev);
858
            ResultSet rs = stmt.executeQuery();
859
            if (rs.next()) 
860
            {
861
                guid = rs.getString(1);
862
            } 
863
            else
864
            {
865
            	throw new McdbDocNotFoundException("No guid registered for docid " + docid + "." + rev);
866
            }
867
            
868
        } catch (SQLException e) {
869
            logMetacat.error("Error while looking up the guid: " 
870
                    + e.getMessage());
871
        } finally {
872
            // Return database connection to the pool
873
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
874
        }
875
        
876
        return guid;
877
    }
878
    
879
    public boolean systemMetadataExists(String guid) {
880
		logMetacat.debug("looking up system metadata for guid " + guid);
881
		boolean exists = false;
882
		String query = "select guid from systemmetadata where guid = ?";
883

    
884
		DBConnection dbConn = null;
885
		int serialNumber = -1;
886
		try {
887
			// Get a database connection from the pool
888
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
889
			serialNumber = dbConn.getCheckOutSerialNumber();
890

    
891
			// Execute the insert statement
892
			PreparedStatement stmt = dbConn.prepareStatement(query);
893
			stmt.setString(1, guid);
894
			ResultSet rs = stmt.executeQuery();
895
			if (rs.next()) {
896
				exists = true;
897
			}
898

    
899
		} catch (SQLException e) {
900
			logMetacat.error("Error while looking up the system metadata: "
901
					+ e.getMessage());
902
		} finally {
903
			// Return database connection to the pool
904
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
905
		}
906

    
907
		return exists;
908
	}
909
    
910
    /**
911
     * creates a system metadata mapping and adds additional fields from sysmeta
912
     * to the table for quick searching.
913
     * 
914
     * @param guid the id to insert
915
     * @param localId the systemMetadata object to get the local id for
916
     * @throws McdbDocNotFoundException 
917
     */
918
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
919
    {
920
    	String guid = sysmeta.getIdentifier().getValue();
921
    	// insert the record
922
        insertSystemMetadata(guid);
923
        // update with the values
924
        updateSystemMetadata(sysmeta);
925
    }
926
        
927
    
928
    /**
929
     * update a mapping
930
     * @param guid
931
     * @param localId
932
     */
933
    public void updateMapping(String guid, String localId)
934
    {
935
    	
936
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
937
        int serialNumber = -1;
938
        DBConnection dbConn = null;
939
        try {
940
            // Parse the localId into scope and rev parts
941
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
942
            String docid = acc.getDocid();
943
            int rev = 1;
944
            if(acc.getRev() != null)
945
            {
946
              rev = (new Integer(acc.getRev()).intValue());
947
            }
948

    
949
            // Get a database connection from the pool
950
            dbConn = 
951
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
952
            serialNumber = dbConn.getCheckOutSerialNumber();
953

    
954
            // Execute the update statement
955
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid = ?";
956
            PreparedStatement stmt = dbConn.prepareStatement(query);
957
            stmt.setString(1, docid);
958
            stmt.setInt(2, rev);
959
            stmt.setString(3, guid);
960
            int rows = stmt.executeUpdate();
961

    
962
            stmt.close();
963
        } catch (SQLException e) {
964
            e.printStackTrace();
965
            logMetacat.error("SQL error while updating a mapping identifier: " 
966
                    + e.getMessage());
967
        } catch (NumberFormatException e) {
968
            e.printStackTrace();
969
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
970
                    + e.getMessage());
971
        } catch (AccessionNumberException e) {
972
            e.printStackTrace();
973
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
974
                    + e.getMessage());
975
        } finally {
976
            // Return database connection to the pool
977
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
978
        }
979
        logMetacat.debug("done updating mapping");
980
    }
981
        
982
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
983
            String checksum, String checksumAlgorithm, String originMemberNode,
984
            String authoritativeMemberNode, long modifiedDate, String submitter, 
985
            String guid, String objectFormat, BigInteger size, boolean replicationAllowed,
986
            int numberReplicas, String obsoletes, String obsoletedBy, BigInteger serialVersion)
987
    {
988
        DBConnection dbConn = null;
989
        int serialNumber = -1;
990
        
991
        try {
992
            // Get a database connection from the pool
993
            dbConn = 
994
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
995
            serialNumber = dbConn.getCheckOutSerialNumber();
996

    
997
            // Execute the insert statement
998
            String query = "update " + TYPE_SYSTEM_METADATA + 
999
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1000
                "origin_member_node, authoritive_member_node, date_modified, " +
1001
                "submitter, object_format, size, replication_allowed, number_replicas, " +
1002
                "obsoletes, obsoleted_by, serial_version) " +
1003
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1004
            PreparedStatement stmt = dbConn.prepareStatement(query);
1005
            
1006
            //data values
1007
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1008
            stmt.setString(2, rightsHolder);
1009
            stmt.setString(3, checksum);
1010
            stmt.setString(4, checksumAlgorithm);
1011
            stmt.setString(5, originMemberNode);
1012
            stmt.setString(6, authoritativeMemberNode);
1013
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1014
            stmt.setString(8, submitter);
1015
            stmt.setString(9, objectFormat);
1016
            stmt.setString(10, size.toString());
1017
            stmt.setBoolean(11, replicationAllowed);
1018
            stmt.setInt(12, numberReplicas);
1019
            stmt.setString(13, obsoletes);
1020
            stmt.setString(14, obsoletedBy);
1021
            stmt.setString(15, serialVersion.toString());
1022

    
1023
            //where clause
1024
            stmt.setString(16, guid);
1025
            logMetacat.debug("stmt: " + stmt.toString());
1026
            //execute
1027
            int rows = stmt.executeUpdate();
1028

    
1029
            stmt.close();
1030
        } catch (SQLException e) {
1031
            e.printStackTrace();
1032
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1033
                    + e.getMessage());
1034
        } catch (NumberFormatException e) {
1035
            e.printStackTrace();
1036
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1037
                    + e.getMessage());
1038
        } finally {
1039
            // Return database connection to the pool
1040
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1041
        }
1042
    }
1043
    
1044
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1045
    {
1046
        DBConnection dbConn = null;
1047
        int serialNumber = -1;
1048
        
1049
        try {
1050
            // Get a database connection from the pool
1051
            dbConn = 
1052
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1053
            serialNumber = dbConn.getCheckOutSerialNumber();
1054

    
1055
            // remove existing values first
1056
            String delete = "delete from systemMetadataReplicationPolicy " + 
1057
            "where guid = ? and policy = ?";
1058
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1059
	        //data values
1060
	        stmt.setString(1, guid);
1061
	        stmt.setString(2, policy);
1062
	        //execute
1063
	        int deletedCount = stmt.executeUpdate();
1064
	        stmt.close();
1065
            
1066
            for (String memberNode: memberNodes) {
1067
	            // Execute the insert statement
1068
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1069
	                "(guid, policy, member_node) " +
1070
	                "values (?, ?, ?)";
1071
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1072
	            
1073
	            //data values
1074
	            insertStatement.setString(1, guid);
1075
	            insertStatement.setString(2, policy);
1076
	            insertStatement.setString(3, memberNode);
1077
	            //execute
1078
	            int rows = insertStatement.executeUpdate();
1079
	            insertStatement.close();
1080
            }
1081
        } catch (SQLException e) {
1082
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1083
        } finally {
1084
            // Return database connection to the pool
1085
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1086
        }
1087
    }
1088
    
1089
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1090
        DBConnection dbConn = null;
1091
        int serialNumber = -1;
1092
        
1093
        try {
1094
            // Get a database connection from the pool
1095
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1096
            serialNumber = dbConn.getCheckOutSerialNumber();
1097

    
1098
            // remove existing values first
1099
            String delete = "delete from systemMetadataReplicationStatus " + 
1100
            "where guid = ?";
1101
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1102
	        //data values
1103
	        stmt.setString(1, guid);
1104
	        //execute
1105
	        int deletedCount = stmt.executeUpdate();
1106
	        stmt.close();
1107
            
1108
	        if (replicas != null) {
1109
	            for (Replica replica: replicas) {
1110
		            // Execute the insert statement
1111
		            String insert = "insert into systemMetadataReplicationStatus " + 
1112
		                "(guid, member_node, status, date_verified) " +
1113
		                "values (?, ?, ?, ?)";
1114
		            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1115
		            
1116
		            //data values
1117
		            String memberNode = replica.getReplicaMemberNode().getValue();
1118
		            String status = replica.getReplicationStatus().toString();
1119
		            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1120
		            insertStatement.setString(1, guid);
1121
		            insertStatement.setString(2, memberNode);
1122
		            insertStatement.setString(3, status);
1123
		            insertStatement.setDate(4, sqlDate);
1124
	
1125
		            //execute
1126
		            int rows = insertStatement.executeUpdate();
1127
		            insertStatement.close();
1128
	            }
1129
	        }
1130
        } catch (SQLException e) {
1131
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1132
        } finally {
1133
            // Return database connection to the pool
1134
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1135
        }
1136
    }
1137
    
1138
    /**
1139
     * Insert the system metadata fields into the db
1140
     * @param sm
1141
     * @throws McdbDocNotFoundException 
1142
     */
1143
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1144
    	
1145
        Boolean replicationAllowed = false;
1146
		Integer numberReplicas = -1;
1147
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1148
    	if (replicationPolicy != null) {
1149
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1150
    		numberReplicas = replicationPolicy.getNumberReplicas();
1151
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1152
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1153
    	}
1154

    
1155
    	// the main systemMetadata fields
1156
		updateSystemMetadataFields(
1157
				sm.getDateUploaded() == null ? null: sm.getDateUploaded().getTime(),
1158
				sm.getRightsHolder() == null ? null: sm.getRightsHolder().getValue(), 
1159
				sm.getChecksum() == null ? null: sm.getChecksum().getValue(), 
1160
				sm.getChecksum() == null ? null: sm.getChecksum().getAlgorithm(), 
1161
				sm.getOriginMemberNode() == null ? null: sm.getOriginMemberNode().getValue(),
1162
				sm.getAuthoritativeMemberNode() == null ? null: sm.getAuthoritativeMemberNode().getValue(), 
1163
				sm.getDateSysMetadataModified() == null ? null: sm.getDateSysMetadataModified().getTime(),
1164
				sm.getSubmitter() == null ? null: sm.getSubmitter().getValue(), 
1165
        sm.getIdentifier().getValue(),
1166
        sm.getFormatId() == null ? null: sm.getFormatId().getValue(),
1167
        sm.getSize(),
1168
        replicationAllowed, 
1169
        numberReplicas,
1170
        sm.getObsoletes() == null ? null:sm.getObsoletes().getValue(),
1171
        sm.getObsoletedBy() == null ? null: sm.getObsoletedBy().getValue(),
1172
        sm.getSerialVersion()
1173
        );
1174
        
1175
        String guid = sm.getIdentifier().getValue();
1176
        
1177
        // save replication policies
1178
        if (replicationPolicy != null) {
1179
		    List<String> nodes = null;
1180
		    String policy = null;
1181
		    
1182
		    // check for null 
1183
		    if (replicationPolicy.getBlockedMemberNodeList() != null) {
1184
			    nodes = new ArrayList<String>();
1185
			    policy = "blocked";
1186
			    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1187
			    	nodes.add(node.getValue());
1188
			    }
1189
			    this.insertReplicationPolicy(guid, policy, nodes);
1190
		    }
1191
		    
1192
		    if (replicationPolicy.getPreferredMemberNodeList() != null) {
1193
			    nodes = new ArrayList<String>();
1194
			    policy = "preferred";
1195
			    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1196
			    	nodes.add(node.getValue());
1197
			    }
1198
		        this.insertReplicationPolicy(guid, policy, nodes);
1199
		    }
1200
        }
1201
        
1202
        // save replica information
1203
        this.insertReplicationStatus(guid, sm.getReplicaList());
1204
        
1205
        // save access policy
1206
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1207
        if (accessPolicy != null) {
1208
        	try {
1209
				this.insertAccessPolicy(guid, accessPolicy);
1210
			} catch (AccessException e) {
1211
				throw new McdbDocNotFoundException(e);
1212
			}
1213
        }
1214
    }
1215
    
1216
    /**
1217
     * Creates Metacat access rules and inserts them
1218
     * @param accessPolicy
1219
     * @throws McdbDocNotFoundException
1220
     * @throws AccessException
1221
     */
1222
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1223
    	
1224
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1225
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1226
        	List<Subject> subjects = accessRule.getSubjectList();
1227
        	List<Permission> permissions = accessRule.getPermissionList();
1228
        	for (Subject subject: subjects) {
1229
    			XMLAccessDAO accessDAO = new XMLAccessDAO();
1230
        		accessDAO.setPrincipalName(subject.getValue());
1231
    			accessDAO.setGuid(guid);
1232
    			accessDAO.setPermType(AccessControlInterface.ALLOW);
1233
    			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1234
    			for (Permission permission: permissions) {
1235
    				Long metacatPermission = new Long(convertPermission(permission));
1236
        			accessDAO.addPermission(metacatPermission);
1237
    			}
1238
    			accessDAOs.add(accessDAO);
1239
        	}
1240
        }
1241
        
1242
        // use GUID to update
1243
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1244
        accessController.replaceAccess(guid, accessDAOs);
1245
        
1246
        
1247
    }
1248
    
1249
    /**
1250
     * Lookup access policy from Metacat
1251
     * @param guid
1252
     * @return
1253
     * @throws McdbDocNotFoundException
1254
     * @throws AccessException
1255
     */
1256
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1257
        AccessPolicy accessPolicy = new AccessPolicy();
1258

    
1259
    	// use GUID to look up the access
1260
        XMLAccessAccess accessController  = new XMLAccessAccess(true);
1261
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(guid);
1262
        for (XMLAccessDAO accessDAO: accessDAOs) {
1263
        	AccessRule accessRule = new AccessRule();    	
1264
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1265
        	accessRule.addPermission(permission);
1266
        	Subject subject = new Subject();
1267
        	subject.setValue(accessDAO.getPrincipalName());
1268
        	accessRule.addSubject(subject);
1269
            accessPolicy.addAllow(accessRule);
1270
        }
1271
        return accessPolicy;
1272
    }
1273
    
1274
    public int convertPermission(Permission permission) {
1275
    	if (permission.equals(Permission.READ)) {
1276
    		return AccessControlInterface.READ;
1277
    	}
1278
    	if (permission.equals(Permission.WRITE)) {
1279
    		return AccessControlInterface.WRITE;
1280
    	}
1281
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1282
    		return AccessControlInterface.CHMOD;
1283
    	}
1284
		return -1;
1285
    }
1286
    
1287
    public Permission convertPermission(int permission) {
1288
    	if (permission == AccessControlInterface.READ) {
1289
    		return Permission.READ;
1290
    	}
1291
    	if (permission == AccessControlInterface.WRITE) {
1292
    		return Permission.WRITE;
1293
    	}
1294
    	if (permission == AccessControlInterface.CHMOD) {
1295
    		return Permission.CHANGE_PERMISSION;
1296
    	}
1297
		return null;
1298
    }
1299
    
1300
    /**
1301
     * Lookup a localId given the GUID. If
1302
     * the identifier is not found, throw an exception.
1303
     * 
1304
     * @param guid the global identifier to look up
1305
     * @return String containing the corresponding LocalId
1306
     * @throws McdbDocNotFoundException if the identifier is not found
1307
     */
1308
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1309
      
1310
      String db_guid = "";
1311
      String docid = "";
1312
      int rev = 0;
1313
      
1314
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1315
      
1316
      DBConnection dbConn = null;
1317
      int serialNumber = -1;
1318
      try {
1319
          // Get a database connection from the pool
1320
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1321
          serialNumber = dbConn.getCheckOutSerialNumber();
1322
          
1323
          // Execute the insert statement
1324
          PreparedStatement stmt = dbConn.prepareStatement(query);
1325
          stmt.setString(1, guid);
1326
          ResultSet rs = stmt.executeQuery();
1327
          if (rs.next()) {
1328
              db_guid = rs.getString(1);
1329
              docid = rs.getString(2);
1330
              rev = rs.getInt(3);
1331
              assert(db_guid.equals(guid));
1332
          } else {
1333
              throw new McdbDocNotFoundException("Document not found:" + guid);
1334
          }
1335
          stmt.close();
1336
      } catch (SQLException e) {
1337
          logMetacat.error("Error while looking up the local identifier: " 
1338
                  + e.getMessage());
1339
      } finally {
1340
          // Return database connection to the pool
1341
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1342
      }
1343
      return docid + "." + rev;
1344
    }
1345
    
1346
    /**
1347
     * query the systemmetadata table based on the given parameters
1348
     * @param startTime
1349
     * @param endTime
1350
     * @param objectFormat
1351
     * @param replicaStatus
1352
     * @param start
1353
     * @param count
1354
     * @return ObjectList
1355
     * @throws SQLException 
1356
     * @throws ServiceException 
1357
     * @throws PropertyNotFoundException 
1358
     */
1359
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1360
            ObjectFormatIdentifier objectFormatId, boolean replicaStatus, int start, int count) throws SQLException, PropertyNotFoundException, ServiceException
1361
    {
1362
        ObjectList ol = new ObjectList();
1363
        int total = 0;
1364
        DBConnection dbConn = null;
1365
        int serialNumber = -1;
1366
        
1367
        try {
1368
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1369
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1370
                "date_modified, submitter, object_format, size from systemmetadata";
1371
            
1372
            boolean f1 = false;
1373
            boolean f2 = false;
1374
            boolean f3 = false;
1375
            
1376
            if (startTime != null) {
1377
                sql += " where systemmetadata.date_modified > ?";
1378
                f1 = true;
1379
            }
1380
            
1381
            if (endTime != null) {
1382
                if (!f1) {
1383
                    sql += " where systemmetadata.date_modified < ?";
1384
                }
1385
                else {
1386
                    sql += " and systemmetadata.date_modified < ?";
1387
                }
1388
                f2 = true;
1389
            }
1390
            
1391
            if (objectFormatId != null) {
1392
                if (!f1 && !f2) {
1393
                    sql += " where object_format = ?";
1394
                }
1395
                else {
1396
                    sql += " and object_format = ?";
1397
                }
1398
                f3 = true;
1399
            }
1400
            
1401
            if (replicaStatus) {
1402
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1403
                if (!f1 && !f2 && !f3) {
1404
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1405
                }
1406
                else {
1407
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1408
                }
1409
            }
1410
            
1411
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1412
            serialNumber = dbConn.getCheckOutSerialNumber();
1413
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1414
            
1415
            if (f1 && f2 && f3) {
1416
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1417
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1418
                stmt.setString(3, objectFormatId.getValue());
1419
            }
1420
            else if (f1 && f2 && !f3) {
1421
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1422
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1423
            }
1424
            else if (f1 && !f2 && f3) {
1425
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1426
                stmt.setString(2, objectFormatId.getValue());
1427
            }
1428
            else if (f1 && !f2 && !f3) {
1429
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1430
            }
1431
            else if (!f1 && f2 && f3) {
1432
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1433
                stmt.setString(2, objectFormatId.getValue());
1434
            }
1435
            else if (!f1 && !f2 && f3) {
1436
                stmt.setString(1, objectFormatId.getValue());
1437
            }
1438
            else if (!f1 && f2 && !f3) {
1439
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1440
            }
1441
            
1442
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1443
            
1444
            ResultSet rs = stmt.executeQuery();
1445
            for (int i=0; i<start; i++) {
1446
                if (rs.next()) {
1447
                    total++;
1448
                } else {
1449
                    break;
1450
                }
1451
            }
1452
            
1453
            int countIndex = 0;
1454
                        
1455
            while (rs.next()) {
1456
                total++;
1457
                if (countIndex >= count) {
1458
                	// allow unlimited (negative number for count)
1459
                	if (count > 0) {
1460
                		break;
1461
                	}
1462
                }
1463
                                
1464
                String guid = rs.getString(1);
1465
                //logMetacat.debug("query found doc with guid " + guid);
1466
                //Timestamp dateUploaded = rs.getTimestamp(2);
1467
                //String rightsHolder = rs.getString(3);
1468
                String checksum = rs.getString(4);
1469
                String checksumAlgorithm = rs.getString(5);
1470
                //String originMemberNode = rs.getString(6);
1471
                //String authoritiveMemberNode = rs.getString(7);
1472
                Timestamp dateModified = rs.getTimestamp(8);
1473
                //String submitter = rs.getString(9);
1474
                String fmtidStr = rs.getString(10);
1475
                String sz = rs.getString(11);
1476
                BigInteger size = new BigInteger("0");
1477
                
1478
                if (sz != null && !sz.trim().equals("")) {
1479
                    size = new BigInteger(rs.getString(11));
1480
                }
1481
                
1482
                ObjectInfo oi = new ObjectInfo();
1483
                
1484
                Identifier id = new Identifier();
1485
                id.setValue(guid);
1486
                oi.setIdentifier(id);
1487
                
1488
                if (dateModified != null) {
1489
                	oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1490
                }
1491
                
1492
                Checksum cs = new Checksum();
1493
                cs.setValue(checksum);
1494
                try {
1495
                	//cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1496
                    cs.setAlgorithm(checksumAlgorithm);
1497
                } catch (Exception e) {
1498
					logMetacat.error("could not parse checksum algorithm", e);
1499
					continue;
1500
				}
1501
                oi.setChecksum(cs);
1502
                
1503
                // set the format type
1504
                ObjectFormatIdentifier fmtid = new ObjectFormatIdentifier();
1505
            	fmtid.setValue(fmtidStr);
1506
                oi.setFormatId(fmtid);
1507
                
1508
//                try {
1509
//	                oi.setFmtid(ObjectFormatCache.getInstance().getFormat(fmtidStr).getFmtid());
1510
//                } catch (NotFound e) {
1511
//                	logMetacat.error("could not find object format: " + fmtidStr, e);
1512
//                	// skip this one
1513
//                	continue;
1514
//				}
1515
                                
1516
                oi.setSize(size);
1517
                
1518
                ol.addObjectInfo(oi);
1519
                countIndex++;
1520
            }
1521
            
1522
            // expend the resultset to get the total count of possible rows
1523
            while (rs.next()) { 
1524
                total++;
1525
            }
1526
        }
1527
        
1528
        finally {
1529
            // Return database connection to the pool
1530
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1531
        }
1532
        
1533
        ol.setStart(start);
1534
        ol.setCount(ol.sizeObjectInfoList());
1535
        ol.setTotal(total);
1536
        
1537
        return ol;
1538
    }
1539
    
1540
    /**
1541
     * create a mapping in the identifier table
1542
     * @param guid
1543
     * @param localId
1544
     */
1545
    public void createMapping(String guid, String localId)
1546
    {        
1547
        
1548
        int serialNumber = -1;
1549
        DBConnection dbConn = null;
1550
        try {
1551

    
1552
            // Parse the localId into scope and rev parts
1553
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1554
            String docid = acc.getDocid();
1555
            int rev = 1;
1556
            if (acc.getRev() != null) {
1557
              rev = (new Integer(acc.getRev()).intValue());
1558
            }
1559

    
1560
            // Get a database connection from the pool
1561
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1562
            serialNumber = dbConn.getCheckOutSerialNumber();
1563

    
1564
            // Execute the insert statement
1565
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1566
            PreparedStatement stmt = dbConn.prepareStatement(query);
1567
            stmt.setString(1, guid);
1568
            stmt.setString(2, docid);
1569
            stmt.setInt(3, rev);
1570
            logMetacat.debug("mapping query: " + stmt.toString());
1571
            int rows = stmt.executeUpdate();
1572

    
1573
            stmt.close();
1574
        } catch (SQLException e) {
1575
            e.printStackTrace();
1576
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1577
                    + e.getMessage());
1578
        } catch (NumberFormatException e) {
1579
            e.printStackTrace();
1580
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1581
                    + e.getMessage());
1582
        } catch (AccessionNumberException e) {
1583
            e.printStackTrace();
1584
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1585
                    + e.getMessage());
1586
        } finally {
1587
            // Return database connection to the pool
1588
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1589
        }
1590
    }
1591
    
1592
    /**
1593
     * create the systemmetadata record
1594
     * @param guid
1595
     */
1596
    private void insertSystemMetadata(String guid)
1597
    {        
1598
        
1599
        int serialNumber = -1;
1600
        DBConnection dbConn = null;
1601
        try {
1602

    
1603
            // Get a database connection from the pool
1604
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1605
            serialNumber = dbConn.getCheckOutSerialNumber();
1606

    
1607
            // Execute the insert statement
1608
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1609
            PreparedStatement stmt = dbConn.prepareStatement(query);
1610
            stmt.setString(1, guid);
1611
            logMetacat.debug("system metadata query: " + stmt.toString());
1612
            int rows = stmt.executeUpdate();
1613

    
1614
            stmt.close();
1615
        } catch (Exception e) {
1616
            e.printStackTrace();
1617
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1618
        } finally {
1619
            // Return database connection to the pool
1620
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1621
        }
1622
    }
1623
    
1624
    public void deleteSystemMetadata(String guid)
1625
    {        
1626
        
1627
        int serialNumber = -1;
1628
        DBConnection dbConn = null;
1629
        String query = null;
1630
        PreparedStatement stmt = null;
1631
        int rows = 0;
1632
        try {
1633

    
1634
            // Get a database connection from the pool
1635
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.deleteSystemMetadata");
1636
            serialNumber = dbConn.getCheckOutSerialNumber();
1637

    
1638
            // remove main system metadata entry
1639
            query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1640
            stmt = dbConn.prepareStatement(query);
1641
            stmt.setString(1, guid);
1642
            logMetacat.debug("delete system metadata: " + stmt.toString());
1643
            rows = stmt.executeUpdate();
1644
            stmt.close();
1645
            
1646
            // remove the systemMetadataReplicationPolicy
1647
            query = "delete from systemMetadataReplicationPolicy " + 
1648
            "where guid = ?";
1649
            stmt = dbConn.prepareStatement(query);
1650
            stmt.setString(1, guid);
1651
            logMetacat.debug("delete systemMetadataReplicationPolicy: " + stmt.toString());
1652
            rows = stmt.executeUpdate();
1653
            stmt.close();
1654
            
1655
            // remove the systemMetadataReplicationStatus
1656
            query = "delete from systemMetadataReplicationStatus " + 
1657
            "where guid = ?";
1658
            stmt = dbConn.prepareStatement(query);
1659
            stmt.setString(1, guid);
1660
            logMetacat.debug("delete systemMetadataReplicationStatus: " + stmt.toString());
1661
            rows = stmt.executeUpdate();
1662
            stmt.close();
1663
            
1664
            // TODO: remove the xml_access?
1665
            // Metacat keeps "deleted" documents so we should not remove access rules.
1666
            
1667
        } catch (Exception e) {
1668
            e.printStackTrace();
1669
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1670
            try {
1671
				dbConn.rollback();
1672
			} catch (SQLException sqle) {
1673
	            logMetacat.error("Error while rolling back delete for record: " + guid, sqle );
1674
			}
1675
        } finally {
1676
            // Return database connection to the pool
1677
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1678
        }
1679
    }
1680
}
1681

    
(37-37/65)