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.ObjectFormat;
47
import org.dataone.service.types.v1.ObjectFormatIdentifier;
48
import org.dataone.service.types.v1.ObjectInfo;
49
import org.dataone.service.types.v1.ObjectList;
50
import org.dataone.service.types.v1.Permission;
51
import org.dataone.service.types.v1.Replica;
52
import org.dataone.service.types.v1.ReplicationPolicy;
53
import org.dataone.service.types.v1.ReplicationStatus;
54
import org.dataone.service.types.v1.Subject;
55
import org.dataone.service.types.v1.SystemMetadata;
56

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

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

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

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

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

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

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

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

    
284

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
(37-37/65)