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.sql.PreparedStatement;
28
import java.sql.ResultSet;
29
import java.sql.SQLException;
30
import java.sql.Timestamp;
31
import java.util.ArrayList;
32
import java.util.Date;
33
import java.util.Hashtable;
34
import java.util.List;
35
import java.util.Vector;
36

    
37
import org.apache.log4j.Logger;
38
import org.dataone.service.types.AccessPolicy;
39
import org.dataone.service.types.AccessRule;
40
import org.dataone.service.types.Checksum;
41
import org.dataone.service.types.ChecksumAlgorithm;
42
import org.dataone.service.types.Identifier;
43
import org.dataone.service.types.NodeReference;
44
import org.dataone.service.types.ObjectFormat;
45
import org.dataone.service.types.ObjectInfo;
46
import org.dataone.service.types.ObjectList;
47
import org.dataone.service.types.Permission;
48
import org.dataone.service.types.Replica;
49
import org.dataone.service.types.ReplicationPolicy;
50
import org.dataone.service.types.ReplicationStatus;
51
import org.dataone.service.types.Subject;
52
import org.dataone.service.types.SystemMetadata;
53

    
54
import edu.ucsb.nceas.metacat.accesscontrol.AccessControlInterface;
55
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessAccess;
56
import edu.ucsb.nceas.metacat.accesscontrol.XMLAccessDAO;
57
import edu.ucsb.nceas.metacat.database.DBConnection;
58
import edu.ucsb.nceas.metacat.database.DBConnectionPool;
59
import edu.ucsb.nceas.metacat.properties.PropertyService;
60
import edu.ucsb.nceas.metacat.shared.AccessException;
61
import edu.ucsb.nceas.metacat.util.DocumentUtil;
62

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

    
83
    /**
84
     * A private constructor that initializes the class when getInstance() is
85
     * called.
86
     */
87
    private IdentifierManager() {}
88

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

    
109
        Identifier sysMetaId = new Identifier();
110
        sysMetaId.setValue(guid);
111
        sysMeta.setIdentifier(sysMetaId);
112
        sysMeta.setDateUploaded(dateUploaded);
113
        Subject rightsHolderSubject = new Subject();
114
        rightsHolderSubject.setValue(rightsHolder);
115
        sysMeta.setRightsHolder(rightsHolderSubject);
116
        Checksum checksumObject = new Checksum();
117
        checksumObject.setValue(checksum);
118
        checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
119
        sysMeta.setChecksum(checksumObject);
120
        NodeReference omn = new NodeReference();
121
        omn.setValue(originMemberNode);
122
        sysMeta.setOriginMemberNode(omn);
123
        NodeReference amn = new NodeReference();
124
        amn.setValue(authoritativeMemberNode);
125
        sysMeta.setAuthoritativeMemberNode(amn);
126
        sysMeta.setDateSysMetadataModified(dateModified);
127
        Subject submitterSubject = new Subject();
128
        submitterSubject.setValue(submitter);
129
        sysMeta.setSubmitter(submitterSubject);
130
        sysMeta.setObjectFormat(ObjectFormat.convert(objectFormat));
131
        sysMeta.setSize(size);
132
        
133
        return sysMeta;
134
    }
135
    
136
    /**
137
     * return a hash of all of the info that is in the systemmetadata table
138
     * @param localId
139
     * @return
140
     */
141
    public Hashtable<String, String> getSystemMetadataInfo(String localId)
142
    throws McdbDocNotFoundException
143
    {
144
        try
145
        {
146
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
147
            localId = acc.getDocid();
148
        }
149
        catch(Exception e)
150
        {
151
            //do nothing. just try the localId as it is
152
        }
153
        Hashtable<String, String> h = new Hashtable<String, String>();
154
        String sql = "select guid, date_uploaded, rights_holder, checksum, checksum_algorithm, " +
155
          "origin_member_node, authoritive_member_node, date_modified, submitter, object_format, size " +
156
          "from systemmetadata where docid = ?";
157
        DBConnection dbConn = null;
158
        int serialNumber = -1;
159
        try 
160
        {
161
            // Get a database connection from the pool
162
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
163
            serialNumber = dbConn.getCheckOutSerialNumber();
164

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

    
241
            // Execute the statement
242
            PreparedStatement stmt = dbConn.prepareStatement(sql);
243
            stmt.setString(1, guid);
244
            ResultSet rs = stmt.executeQuery();
245
            if (rs.next()) 
246
            {
247
                Timestamp dateUploaded = rs.getTimestamp(2);
248
                String rightsHolder = rs.getString(3);
249
                String checksum = rs.getString(4);
250
                String checksumAlgorithm = rs.getString(5);
251
                String originMemberNode = rs.getString(6);
252
                String authoritativeMemberNode = rs.getString(7);
253
                Timestamp dateModified = rs.getTimestamp(8);
254
                String submitter = rs.getString(9);
255
                String objectFormat = rs.getString(10);
256
                long size = new Long(rs.getString(11)).longValue();
257
                
258
                Identifier sysMetaId = new Identifier();
259
                sysMetaId.setValue(guid);
260
                sysMeta.setIdentifier(sysMetaId);
261
                sysMeta.setDateUploaded(dateUploaded);
262
                Subject rightsHolderSubject = new Subject();
263
                rightsHolderSubject.setValue(rightsHolder);
264
                sysMeta.setRightsHolder(rightsHolderSubject);
265
                Checksum checksumObject = new Checksum();
266
                checksumObject.setValue(checksum);
267
                checksumObject.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
268
                sysMeta.setChecksum(checksumObject);
269
                NodeReference omn = new NodeReference();
270
                omn.setValue(originMemberNode);
271
                sysMeta.setOriginMemberNode(omn);
272
                NodeReference amn = new NodeReference();
273
                amn.setValue(authoritativeMemberNode);
274
                sysMeta.setAuthoritativeMemberNode(amn);
275
                sysMeta.setDateSysMetadataModified(dateModified);
276
                Subject submitterSubject = new Subject();
277
                submitterSubject.setValue(submitter);
278
                sysMeta.setSubmitter(submitterSubject);
279
                sysMeta.setObjectFormat(ObjectFormat.convert(objectFormat));
280
                sysMeta.setSize(size);
281
                
282
                stmt.close();
283
            } 
284
            else
285
            {
286
                stmt.close();
287
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
288
                throw new McdbDocNotFoundException("Could not find " + guid);
289
            }
290
            
291
        } 
292
        catch (SQLException e) 
293
        {
294
            e.printStackTrace();
295
            logMetacat.error("Error while getting system metadata for guid " + guid + " : "  
296
                    + e.getMessage());
297
        } 
298
        finally 
299
        {
300
            // Return database connection to the pool
301
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
302
        }
303
        
304
        // look up provenance information
305
        sysMeta.setObsoleteList(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "obsoletes"));
306
        sysMeta.setObsoletedByList(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "obsoletedBy"));
307
        sysMeta.setDescribeList(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "describes"));
308
        sysMeta.setDescribedByList(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "describedBy"));
309
        sysMeta.setDerivedFromList(getSystemMetadataProvenance(sysMeta.getIdentifier().getValue(), "derivedFrom"));
310
        
311
        // look up replication policy
312
        ReplicationPolicy replicationPolicy = new ReplicationPolicy();
313
        replicationPolicy.setBlockedMemberNodeList(getReplicationPolicy(guid, "blocked"));
314
        replicationPolicy.setPreferredMemberNodeList(getReplicationPolicy(guid, "preferred"));
315
		sysMeta.setReplicationPolicy(replicationPolicy);
316
		
317
		// look up replication status
318
		sysMeta.setReplicaList(getReplicationStatus(guid));
319
		
320
		// look up access policy
321
		try {
322
			sysMeta.setAccessPolicy(getAccessPolicy(guid));
323
		} catch (AccessException e) {
324
			throw new McdbDocNotFoundException(e);
325
		}
326
        
327
        return sysMeta;
328
    }
329
    
330
    private List<Identifier> getSystemMetadataProvenance(String guid, String relationship)
331
    	throws McdbDocNotFoundException {
332
    	
333
    	List<Identifier> identifiers = new ArrayList<Identifier>();
334
    	String sql = "select guid, relationship, target_guid " +
335
    		"from systemMetadataProvenance where guid = ? and relationship = ?";
336
	    DBConnection dbConn = null;
337
	    int serialNumber = -1;
338
	    try {
339
	        // Get a database connection from the pool
340
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getSystemMetadataProvenance");
341
	        serialNumber = dbConn.getCheckOutSerialNumber();
342
	
343
	        // Execute the statement
344
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
345
	        stmt.setString(1, guid);
346
	        stmt.setString(2, relationship);
347
	        ResultSet rs = stmt.executeQuery();
348
	        while (rs.next()) 
349
	        {
350
	            String targetGuid = rs.getString(3);
351
	            Identifier id = new Identifier();
352
	            id.setValue(targetGuid);
353
	            identifiers.add(id);
354
	        
355
	        } 
356
	        stmt.close();
357
	        
358
	    } 
359
	    catch (SQLException e) {
360
	        logMetacat.error("Error while getting system metadata provenance for guid " + guid, e);
361
	    } 
362
	    finally {
363
	        // Return database connection to the pool
364
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
365
	    }
366
	    
367
	    return identifiers;
368
	}
369
    
370
    private List<NodeReference> getReplicationPolicy(String guid, String policy)
371
		throws McdbDocNotFoundException {
372
		
373
		List<NodeReference> nodes = new ArrayList<NodeReference>();
374
		String sql = "select guid, policy, member_node " +
375
			"from systemMetadataReplicationPolicy where guid = ? and policy = ?";
376
	    DBConnection dbConn = null;
377
	    int serialNumber = -1;
378
	    try {
379
	        // Get a database connection from the pool
380
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicationPolicy");
381
	        serialNumber = dbConn.getCheckOutSerialNumber();
382
	
383
	        // Execute the statement
384
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
385
	        stmt.setString(1, guid);
386
	        stmt.setString(2, policy);
387
	        ResultSet rs = stmt.executeQuery();
388
	        while (rs.next()) 
389
	        {
390
	            String memberNode = rs.getString(3);
391
	            NodeReference node = new NodeReference();
392
	            node.setValue(memberNode);
393
	            nodes.add(node);
394
	        
395
	        } 
396
	        stmt.close();
397
	        
398
	    } catch (SQLException e) {
399
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
400
	    } 
401
	    finally {
402
	        // Return database connection to the pool
403
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
404
	    }
405
	    
406
	    return nodes;
407
	}
408
    
409
    private List<Replica> getReplicationStatus(String guid) throws McdbDocNotFoundException {
410
		
411
		List<Replica> replicas = new ArrayList<Replica>();
412
		String sql = "select guid, member_node, status, date_verified " +
413
			"from systemMetadataReplicationStatus where guid = ?";
414
	    DBConnection dbConn = null;
415
	    int serialNumber = -1;
416
	    try {
417
	        // Get a database connection from the pool
418
	        dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getReplicas");
419
	        serialNumber = dbConn.getCheckOutSerialNumber();
420
	
421
	        // Execute the statement
422
	        PreparedStatement stmt = dbConn.prepareStatement(sql);
423
	        stmt.setString(1, guid);
424
	        ResultSet rs = stmt.executeQuery();
425
	        while (rs.next()) 
426
	        {
427
	            String memberNode = rs.getString(2);
428
	            String status = rs.getString(3);
429
	            java.sql.Date verified = rs.getDate(4);
430
	            
431
	            Replica replica = new Replica();	            
432
	            NodeReference node = new NodeReference();
433
	            node.setValue(memberNode);
434
	            replica.setReplicaMemberNode(node);
435
	            replica.setReplicationStatus(ReplicationStatus.convert(status));
436
	            replica.setReplicaVerified(new Date(verified.getTime()));
437
	            replicas.add(replica);
438
	        } 
439
	        stmt.close();
440
	        
441
	    } catch (SQLException e) {
442
	        logMetacat.error("Error while getting system metadata replication policy for guid " + guid, e);
443
	    } 
444
	    finally {
445
	        // Return database connection to the pool
446
	        DBConnectionPool.returnDBConnection(dbConn, serialNumber);
447
	    }
448
	    
449
	    return replicas;
450
	}
451
    
452
    /**
453
     * return information on the document with localId.  These are the fields
454
     * from the xml_documents table.  They can be used to contstruct metadata 
455
     * about the object that is stored.
456
     * @param localId
457
     * @return
458
     * @throws McdbDocNotFoundException
459
     */
460
    public Hashtable<String, Object> getDocumentInfo(String localId)
461
        throws McdbDocNotFoundException
462
    {
463
        try
464
        {
465
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
466
            localId = acc.getDocid();
467
        }
468
        catch(Exception e)
469
        {
470
            //do nothing. just try the localId as it is
471
        }
472
        Hashtable<String, Object> h = new Hashtable<String, Object>();
473
        String sql = "select docname, doctype, user_owner, user_updated, " +
474
            "server_location, rev, date_created, date_updated from " + 
475
            "xml_documents where docid like '" + localId + "'";
476
        DBConnection dbConn = null;
477
        int serialNumber = -1;
478
        try 
479
        {
480
            // Get a database connection from the pool
481
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getDocumentInfo");
482
            serialNumber = dbConn.getCheckOutSerialNumber();
483

    
484
            // Execute the insert statement
485
            PreparedStatement stmt = dbConn.prepareStatement(sql);
486
            ResultSet rs = stmt.executeQuery();
487
            if (rs.next()) 
488
            {
489
                String docname = rs.getString(1);
490
                String doctype = rs.getString(2);
491
                String user_owner = rs.getString(3);
492
                String user_updated = rs.getString(4);
493
                String server_location = rs.getString(5);
494
                int rev = rs.getInt(6);
495
                String date_created = rs.getString(7);
496
                String date_updated = rs.getString(8);
497
                h.put("docid", localId);
498
                h.put("docname", docname);
499
                h.put("doctype", doctype);
500
                h.put("user_owner", user_owner);
501
                h.put("user_updated", user_updated);
502
                h.put("server_location", server_location);
503
                h.put("rev", new Integer(rev).toString());
504
                h.put("date_created", date_created);
505
                h.put("date_updated", date_updated);
506
                
507
                stmt.close();
508
            } 
509
            else
510
            {
511
                stmt.close();
512
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
513
                throw new McdbDocNotFoundException("2Could not find document " + localId);
514
            }
515
            
516
            String sql2 = "select principal_name, permission, perm_type, perm_order from xml_access " +
517
            "where docid like '" + localId + "'";
518
            logMetacat.debug("executing sql: " + sql2);
519
            PreparedStatement stmt2 = dbConn.prepareStatement(sql2);
520
            rs = stmt2.executeQuery();
521
            Vector accessVector = new Vector();
522
            while(rs.next())
523
            {
524
                Hashtable accessHash = new Hashtable();
525
                String principal_name = rs.getString(1);
526
                String permission = rs.getString(2);
527
                String permissionType = rs.getString(3);
528
                String permissionOrder = rs.getString(4);
529
                accessHash.put("principal_name", principal_name);
530
                accessHash.put("permission", permission);
531
                accessHash.put("permission_type", permissionType);
532
                accessHash.put("permission_order", permissionOrder);
533
                logMetacat.debug("accessHash: " + accessHash.toString());
534
                accessVector.add(accessHash);
535
            }
536
            h.put("access", accessVector);
537
        } 
538
        catch (SQLException e) 
539
        {
540
            e.printStackTrace();
541
            logMetacat.error("Error while getting document info for localid " + localId + " : "  
542
                    + e.getMessage());
543
        } 
544
        finally 
545
        {
546
            // Return database connection to the pool
547
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
548
        }
549
        return h;
550
    }
551
    
552
    /**
553
     * return the newest rev for a given localId
554
     * @param localId
555
     * @return
556
     */
557
    public int getLatestRevForLocalId(String localId)
558
        throws McdbDocNotFoundException
559
    {
560
        try
561
        {
562
            AccessionNumber acc = new AccessionNumber(localId, "NONE");
563
            localId = acc.getDocid();
564
        }
565
        catch(Exception e)
566
        {
567
            //do nothing. just try the localId as it is
568
        }
569
        int rev = 0;
570
        String sql = "select rev from xml_documents where docid like '" + localId + "'";
571
        DBConnection dbConn = null;
572
        int serialNumber = -1;
573
        try 
574
        {
575
            // Get a database connection from the pool
576
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLatestRevForLocalId");
577
            serialNumber = dbConn.getCheckOutSerialNumber();
578

    
579
            // Execute the insert statement
580
            PreparedStatement stmt = dbConn.prepareStatement(sql);
581
            ResultSet rs = stmt.executeQuery();
582
            if (rs.next()) 
583
            {
584
                rev = rs.getInt(1);
585
                stmt.close();
586
            } 
587
            else
588
            {
589
                stmt.close();
590
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
591
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
592
            }
593
        } 
594
        catch (SQLException e) 
595
        {
596
            logMetacat.error("Error while looking up the guid: " 
597
                    + e.getMessage());
598
        } 
599
        finally 
600
        {
601
            // Return database connection to the pool
602
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
603
        }
604
        return rev;
605
    }
606
    
607
    /**
608
     * return all local ids in the object store that do not have associated
609
     * system metadata
610
     */
611
    public List<String> getLocalIdsWithNoSystemMetadata()
612
    {
613
        Vector<String> ids = new Vector<String>();
614
        String sql = "select docid, rev from xml_documents " +
615
        		"where docid not in " +
616
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
617
        DBConnection dbConn = null;
618
        int serialNumber = -1;
619
        try 
620
        {
621
            // Get a database connection from the pool
622
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
623
            serialNumber = dbConn.getCheckOutSerialNumber();
624

    
625
            // Execute the insert statement
626
            PreparedStatement stmt = dbConn.prepareStatement(sql);
627
            ResultSet rs = stmt.executeQuery();
628
            while (rs.next()) 
629
            {
630
                String localid = rs.getString(1);
631
                String rev = rs.getString(2);
632
                localid += "." + rev;
633
                logMetacat.debug("id to add SM for: " + localid);
634
                ids.add(localid);
635
            } 
636
            stmt.close();
637
        } 
638
        catch (SQLException e) 
639
        {
640
            logMetacat.error("Error while looking up the guid: " 
641
                    + e.getMessage());
642
        } 
643
        finally 
644
        {
645
            // Return database connection to the pool
646
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
647
        }
648
        
649
        return ids;
650
    }
651
    
652
    /**
653
     * return a listing of all local ids in the object store
654
     * @return a list of all local ids in metacat
655
     */
656
    public List<String> getAllLocalIds()
657
       throws Exception
658
    {
659
        Vector<String> ids = new Vector<String>();
660
        String sql = "select docid from xml_documents";
661
        DBConnection dbConn = null;
662
        int serialNumber = -1;
663
        try 
664
        {
665
            // Get a database connection from the pool
666
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
667
            serialNumber = dbConn.getCheckOutSerialNumber();
668

    
669
            // Execute the insert statement
670
            PreparedStatement stmt = dbConn.prepareStatement(sql);
671
            ResultSet rs = stmt.executeQuery();
672
            while (rs.next()) 
673
            {
674
                String localid = rs.getString(1);
675
                ids.add(localid);
676
            } 
677
            stmt.close();
678
        } 
679
        catch (SQLException e) 
680
        {
681
            logMetacat.error("Error while looking up the guid: " 
682
                    + e.getMessage());
683
        } 
684
        finally 
685
        {
686
            // Return database connection to the pool
687
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
688
        }
689
        return ids;
690
    }
691
    
692
    /**
693
     * returns a list of system metadata-only guids since the given date
694
     * @return a list of system ids in metacat that do not correspond to objects
695
     * TODO: need to check which server they are on
696
     */
697
    public List<String> getUpdatedSystemMetadataIds(Date since)
698
       throws Exception
699
    {
700
        List<String> ids = new Vector<String>();
701
        String sql = 
702
        	"select guid from " + TYPE_SYSTEM_METADATA +
703
        	" where guid not in " +
704
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
705
        	" and date_modified > ?";
706
        DBConnection dbConn = null;
707
        int serialNumber = -1;
708
        try 
709
        {
710
            // Get a database connection from the pool
711
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
712
            serialNumber = dbConn.getCheckOutSerialNumber();
713

    
714
            // Execute the insert statement
715
            PreparedStatement stmt = dbConn.prepareStatement(sql);
716
            stmt.setDate(1, new java.sql.Date(since.getTime()));
717
            ResultSet rs = stmt.executeQuery();
718
            while (rs.next()) 
719
            {
720
                String guid = rs.getString(1);
721
                ids.add(guid);
722
            } 
723
            stmt.close();
724
        } 
725
        catch (SQLException e) 
726
        {
727
            logMetacat.error("Error while looking up the updated guids: " 
728
                    + e.getMessage());
729
        } 
730
        finally 
731
        {
732
            // Return database connection to the pool
733
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
734
        }
735
        return ids;
736
    }
737
    
738

    
739
    
740
    /**
741
     * Determine if an identifier exists already, returning true if so.
742
     * 
743
     * @param guid the global identifier to look up
744
     * @return boolean true if the identifier exists
745
     */
746
    public boolean identifierExists(String guid)
747
    {
748
        boolean idExists = false;
749
        try {
750
            String id = getLocalId(guid);
751
            if (id != null) {
752
                idExists = true;
753
            }
754
        } catch (McdbDocNotFoundException e) {
755
            idExists = false;
756
        }
757
        return idExists;
758
    }
759
    
760
    /**
761
     * 
762
     * @param guid
763
     * @param rev
764
     * @return
765
     */
766
    public String generateLocalId(String guid, int rev)
767
    {
768
        return generateLocalId(guid, rev, false);
769
    }
770

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

    
904
            // Get a database connection from the pool
905
            dbConn = 
906
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
907
            serialNumber = dbConn.getCheckOutSerialNumber();
908

    
909
            // Execute the update statement
910
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
911
            PreparedStatement stmt = dbConn.prepareStatement(query);
912
            stmt.setString(1, docid);
913
            stmt.setInt(2, rev);
914
            int rows = stmt.executeUpdate();
915

    
916
            stmt.close();
917
        } catch (SQLException e) {
918
            e.printStackTrace();
919
            logMetacat.error("SQL error while updating a mapping identifier: " 
920
                    + e.getMessage());
921
        } catch (NumberFormatException e) {
922
            e.printStackTrace();
923
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
924
                    + e.getMessage());
925
        } catch (AccessionNumberException e) {
926
            e.printStackTrace();
927
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
928
                    + e.getMessage());
929
        } finally {
930
            // Return database connection to the pool
931
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
932
        }
933
        logMetacat.debug("done updating mapping");
934
    }
935
        
936
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
937
            String checksum, String checksumAlgorithm, String originMemberNode,
938
            String authoritativeMemberNode, long modifiedDate, String submitter, 
939
            String guid, String objectFormat, long size, boolean replicationAllowed,
940
            int numberReplicas)
941
    {
942
        DBConnection dbConn = null;
943
        int serialNumber = -1;
944
        
945
        try {
946
            // Get a database connection from the pool
947
            dbConn = 
948
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
949
            serialNumber = dbConn.getCheckOutSerialNumber();
950

    
951
            // Execute the insert statement
952
            String query = "update " + TYPE_SYSTEM_METADATA + 
953
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
954
                "origin_member_node, authoritive_member_node, date_modified, " +
955
                "submitter, object_format, size, replication_allowed, number_replicas) " +
956
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
957
            PreparedStatement stmt = dbConn.prepareStatement(query);
958
            
959
            //data values
960
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
961
            stmt.setString(2, rightsHolder);
962
            stmt.setString(3, checksum);
963
            stmt.setString(4, checksumAlgorithm);
964
            stmt.setString(5, originMemberNode);
965
            stmt.setString(6, authoritativeMemberNode);
966
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
967
            stmt.setString(8, submitter);
968
            stmt.setString(9, objectFormat);
969
            stmt.setString(10, new Long(size).toString());
970
            stmt.setBoolean(11, replicationAllowed);
971
            stmt.setInt(12, numberReplicas);
972
            //where clause
973
            stmt.setString(13, guid);
974
            logMetacat.debug("stmt: " + stmt.toString());
975
            //execute
976
            int rows = stmt.executeUpdate();
977

    
978
            stmt.close();
979
        } catch (SQLException e) {
980
            e.printStackTrace();
981
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
982
                    + e.getMessage());
983
        } catch (NumberFormatException e) {
984
            e.printStackTrace();
985
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
986
                    + e.getMessage());
987
        } finally {
988
            // Return database connection to the pool
989
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
990
        }
991
    }
992
    
993
    private void insertSystemMetadataProvenance(String guid, String relationship, List<String> targetGuids)
994
    {
995
        DBConnection dbConn = null;
996
        int serialNumber = -1;
997
        
998
        try {
999
            // Get a database connection from the pool
1000
            dbConn = 
1001
                DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadataProvenance");
1002
            serialNumber = dbConn.getCheckOutSerialNumber();
1003

    
1004
            // remove existing values first
1005
            String delete = "delete from systemMetadataProvenance " + 
1006
            "where guid = ? and relationship = ?";
1007
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1008
	        //data values
1009
	        stmt.setString(1, guid);
1010
	        stmt.setString(2, relationship);
1011
	        //execute
1012
	        int deletedCount = stmt.executeUpdate();
1013
	        stmt.close();
1014
            
1015
            for (String targetGuid: targetGuids) {
1016
	            // Execute the insert statement
1017
	            String insert = "insert into systemMetadataProvenance " + 
1018
	                "(guid, relationship, target_guid) " +
1019
	                "values (?, ?, ?)";
1020
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1021
	            
1022
	            //data values
1023
	            insertStatement.setString(1, guid);
1024
	            insertStatement.setString(2, relationship);
1025
	            insertStatement.setString(3, targetGuid);
1026
	            //execute
1027
	            int rows = insertStatement.executeUpdate();
1028
	            insertStatement.close();
1029
            }
1030
        } catch (SQLException e) {
1031
            logMetacat.error("SQL error while adding systemMetadataProvenance for: " + guid, e); 
1032
        } finally {
1033
            // Return database connection to the pool
1034
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1035
        }
1036
    }
1037
    
1038
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1039
    {
1040
        DBConnection dbConn = null;
1041
        int serialNumber = -1;
1042
        
1043
        try {
1044
            // Get a database connection from the pool
1045
            dbConn = 
1046
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1047
            serialNumber = dbConn.getCheckOutSerialNumber();
1048

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

    
1092
            // remove existing values first
1093
            String delete = "delete from systemMetadataReplicationStatus " + 
1094
            "where guid = ?";
1095
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1096
	        //data values
1097
	        stmt.setString(1, guid);
1098
	        //execute
1099
	        int deletedCount = stmt.executeUpdate();
1100
	        stmt.close();
1101
            
1102
            for (Replica replica: replicas) {
1103
	            // Execute the insert statement
1104
	            String insert = "insert into systemMetadataReplicationStatus " + 
1105
	                "(guid, member_node, status, date_verified) " +
1106
	                "values (?, ?, ?, ?)";
1107
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1108
	            
1109
	            //data values
1110
	            String memberNode = replica.getReplicaMemberNode().getValue();
1111
	            String status = replica.getReplicationStatus().toString();
1112
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1113
	            insertStatement.setString(1, guid);
1114
	            insertStatement.setString(2, memberNode);
1115
	            insertStatement.setString(3, status);
1116
	            insertStatement.setDate(4, sqlDate);
1117

    
1118
	            //execute
1119
	            int rows = insertStatement.executeUpdate();
1120
	            insertStatement.close();
1121
            }
1122
        } catch (SQLException e) {
1123
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1124
        } finally {
1125
            // Return database connection to the pool
1126
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1127
        }
1128
    }
1129
    
1130
    /**
1131
     * Insert the system metadata fields into the db
1132
     * @param sm
1133
     * @throws McdbDocNotFoundException 
1134
     */
1135
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1136
    	
1137
        Boolean replicationAllowed = false;
1138
		Integer numberReplicas = -1;
1139
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1140
    	if (replicationPolicy != null) {
1141
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1142
    		numberReplicas = replicationPolicy.getNumberReplicas();
1143
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1144
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1145
    	}
1146

    
1147
    	// the main systemMetadata fields
1148
		updateSystemMetadataFields(
1149
                sm.getDateUploaded().getTime(),
1150
                sm.getRightsHolder().getValue(), 
1151
                sm.getChecksum().getValue(), 
1152
                sm.getChecksum().getAlgorithm().name(), 
1153
                sm.getOriginMemberNode().getValue(),
1154
                sm.getAuthoritativeMemberNode().getValue(), 
1155
                sm.getDateSysMetadataModified().getTime(),
1156
                sm.getSubmitter().getValue(), 
1157
                sm.getIdentifier().getValue(),
1158
                sm.getObjectFormat().toString(),
1159
                sm.getSize(),
1160
                replicationAllowed, 
1161
                numberReplicas);
1162
        
1163
        // add provenance information
1164
        String guid = sm.getIdentifier().getValue();
1165
        List<String> targetGuids = null;
1166
        String relationship = null;
1167
        
1168
        relationship = "obsoletedBy";
1169
        targetGuids = new ArrayList<String>();
1170
        for (Identifier id: sm.getObsoletedByList()) {
1171
        	targetGuids.add(id.getValue());
1172
        }
1173
        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1174
        
1175
        relationship = "obsoletes";
1176
        targetGuids = new ArrayList<String>();
1177
        for (Identifier id: sm.getObsoleteList()) {
1178
        	targetGuids.add(id.getValue());
1179
        }
1180
        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1181
        
1182
        relationship = "describes";
1183
        targetGuids = new ArrayList<String>();
1184
        for (Identifier id: sm.getDescribeList()) {
1185
        	targetGuids.add(id.getValue());
1186
        }
1187
        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1188
        
1189
        relationship = "describedBy";
1190
        targetGuids = new ArrayList<String>();
1191
        for (Identifier id: sm.getDescribedByList()) {
1192
        	targetGuids.add(id.getValue());
1193
        }
1194
        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1195
        
1196
        relationship = "derivedFrom";
1197
        targetGuids = new ArrayList<String>();
1198
        for (Identifier id: sm.getDerivedFromList()) {
1199
        	targetGuids.add(id.getValue());
1200
        }
1201
        this.insertSystemMetadataProvenance(guid, relationship, targetGuids);
1202
                
1203
        // save replication policies
1204
        if (replicationPolicy != null) {
1205
		    List<String> nodes = null;
1206
		    String policy = null;
1207
		    
1208
		    nodes = new ArrayList<String>();
1209
		    policy = "blocked";
1210
		    for (NodeReference node: replicationPolicy.getBlockedMemberNodeList()) {
1211
		    	nodes.add(node.getValue());
1212
		    }
1213
		    this.insertReplicationPolicy(guid, policy, nodes);
1214
		    
1215
		    nodes = new ArrayList<String>();
1216
		    policy = "preferred";
1217
		    for (NodeReference node: replicationPolicy.getPreferredMemberNodeList()) {
1218
		    	nodes.add(node.getValue());
1219
		    }
1220
	        this.insertReplicationPolicy(guid, policy, nodes);
1221
        }
1222
        
1223
        // save replica information
1224
        this.insertReplicationStatus(guid, sm.getReplicaList());
1225
        
1226
        // save access policy
1227
        AccessPolicy accessPolicy = sm.getAccessPolicy();
1228
        if (accessPolicy != null) {
1229
        	try {
1230
				this.insertAccessPolicy(guid, accessPolicy);
1231
			} catch (AccessException e) {
1232
				throw new McdbDocNotFoundException(e);
1233
			}
1234
        }
1235
    }
1236
    
1237
    /**
1238
     * Creates Metacat access rules and inserts them
1239
     * @param accessPolicy
1240
     * @throws McdbDocNotFoundException
1241
     * @throws AccessException
1242
     */
1243
    private void insertAccessPolicy(String guid, AccessPolicy accessPolicy) throws McdbDocNotFoundException, AccessException {
1244
    	
1245
    	String docid = getLocalId(guid);
1246
    	List<XMLAccessDAO> accessDAOs = new ArrayList<XMLAccessDAO>();
1247
        for (AccessRule accessRule: accessPolicy.getAllowList()) {
1248
        	List<Subject> subjects = accessRule.getSubjectList();
1249
        	List<Identifier> resources = accessRule.getResourceList();
1250
        	List<Permission> permissions = accessRule.getPermissionList();
1251
        	for (Subject subject: subjects) {
1252
        		for (Identifier resource: resources) {
1253
        			docid = getLocalId(resource.getValue());
1254
        			XMLAccessDAO accessDAO = new XMLAccessDAO();
1255
            		accessDAO.setPrincipalName(subject.getValue());
1256
        			accessDAO.setDocId(docid);
1257
        			accessDAO.setPermType(AccessControlInterface.ALLOW);
1258
        			accessDAO.setPermOrder(AccessControlInterface.DENYFIRST);
1259
        			for (Permission permission: permissions) {
1260
        				Long metacatPermission = new Long(convertPermission(permission));
1261
	        			accessDAO.addPermission(metacatPermission);
1262
        			}
1263
        			accessDAOs.add(accessDAO);
1264
        		}
1265
        	}
1266
        }
1267
        
1268
        XMLAccessAccess accessController  = new XMLAccessAccess();
1269
        accessController.replaceAccess(docid, accessDAOs);
1270
        
1271
        
1272
    }
1273
    
1274
    /**
1275
     * Lookup access policy from Metacat
1276
     * @param guid
1277
     * @return
1278
     * @throws McdbDocNotFoundException
1279
     * @throws AccessException
1280
     */
1281
    private AccessPolicy getAccessPolicy(String guid) throws McdbDocNotFoundException, AccessException {
1282
    	String docid = getLocalId(guid);
1283
        XMLAccessAccess accessController  = new XMLAccessAccess();
1284
    	List<XMLAccessDAO> accessDAOs = accessController.getXMLAccessForDoc(docid);
1285
    	AccessRule accessRule = new AccessRule();
1286
    	Identifier resource = new Identifier();
1287
    	resource.setValue(guid);
1288
    	accessRule.addResource(resource);
1289
        for (XMLAccessDAO accessDAO: accessDAOs) {
1290
        	Permission permission = convertPermission(accessDAO.getPermission().intValue());
1291
        	accessRule.addPermission(permission);
1292
        	Subject subject = new Subject();
1293
        	subject.setValue(accessDAO.getPrincipalName());
1294
        	accessRule.addSubject(subject);
1295
        }
1296
        AccessPolicy accessPolicy = new AccessPolicy();
1297
        accessPolicy.addAllow(accessRule);
1298
        return accessPolicy;
1299
    }
1300
    
1301
    public int convertPermission(Permission permission) {
1302
    	if (permission.equals(Permission.READ)) {
1303
    		return AccessControlInterface.READ;
1304
    	}
1305
    	if (permission.equals(Permission.WRITE)) {
1306
    		return AccessControlInterface.WRITE;
1307
    	}
1308
    	if (permission.equals(Permission.CHANGE_PERMISSION)) {
1309
    		return AccessControlInterface.CHMOD;
1310
    	}
1311
		return -1;
1312
    }
1313
    
1314
    public Permission convertPermission(int permission) {
1315
    	if (permission == AccessControlInterface.READ) {
1316
    		return Permission.READ;
1317
    	}
1318
    	if (permission == AccessControlInterface.WRITE) {
1319
    		return Permission.WRITE;
1320
    	}
1321
    	if (permission == AccessControlInterface.CHMOD) {
1322
    		return Permission.CHANGE_PERMISSION;
1323
    	}
1324
		return null;
1325
    }
1326
    
1327
    /**
1328
     * Lookup a localId given the GUID. If
1329
     * the identifier is not found, throw an exception.
1330
     * 
1331
     * @param guid the global identifier to look up
1332
     * @return String containing the corresponding LocalId
1333
     * @throws McdbDocNotFoundException if the identifier is not found
1334
     */
1335
    public String getLocalId(String guid) throws McdbDocNotFoundException {
1336
      
1337
      String db_guid = "";
1338
      String docid = "";
1339
      int rev = 0;
1340
      
1341
      String query = "select guid, docid, rev from " + TYPE_IDENTIFIER + " where guid = ?";
1342
      
1343
      DBConnection dbConn = null;
1344
      int serialNumber = -1;
1345
      try {
1346
          // Get a database connection from the pool
1347
          dbConn = DBConnectionPool.getDBConnection("Identifier.getLocalId");
1348
          serialNumber = dbConn.getCheckOutSerialNumber();
1349
          
1350
          // Execute the insert statement
1351
          PreparedStatement stmt = dbConn.prepareStatement(query);
1352
          stmt.setString(1, guid);
1353
          ResultSet rs = stmt.executeQuery();
1354
          if (rs.next()) {
1355
              db_guid = rs.getString(1);
1356
              docid = rs.getString(2);
1357
              rev = rs.getInt(3);
1358
              assert(db_guid.equals(guid));
1359
          } else {
1360
              throw new McdbDocNotFoundException("Document not found:" + guid);
1361
          }
1362
          stmt.close();
1363
      } catch (SQLException e) {
1364
          logMetacat.error("Error while looking up the local identifier: " 
1365
                  + e.getMessage());
1366
      } finally {
1367
          // Return database connection to the pool
1368
          DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1369
      }
1370
      return docid + "." + rev;
1371
    }
1372
    
1373
    /**
1374
     * query the systemmetadata table based on the given parameters
1375
     * @param startTime
1376
     * @param endTime
1377
     * @param objectFormat
1378
     * @param replicaStatus
1379
     * @param start
1380
     * @param count
1381
     * @return ObjectList
1382
     */
1383
    public ObjectList querySystemMetadata(Date startTime, Date endTime, 
1384
            ObjectFormat objectFormat, boolean replicaStatus, int start, int count)
1385
    {
1386
        ObjectList ol = new ObjectList();
1387
        int total = 0;
1388
        DBConnection dbConn = null;
1389
        int serialNumber = -1;
1390
        
1391
        try
1392
        {
1393
            String sql = "select guid, date_uploaded, rights_holder, checksum, " +
1394
                "checksum_algorithm, origin_member_node, authoritive_member_node, " +
1395
                "date_modified, submitter, object_format, size from systemmetadata";
1396
            
1397
            boolean f1 = false;
1398
            boolean f2 = false;
1399
            boolean f3 = false;
1400
            
1401
            if(startTime != null)
1402
            {
1403
                sql += " where systemmetadata.date_modified > ?";
1404
                f1 = true;
1405
            }
1406
            
1407
            if(endTime != null)
1408
            {
1409
                if(!f1)
1410
                {
1411
                    sql += " where systemmetadata.date_modified < ?";
1412
                }
1413
                else
1414
                {
1415
                    sql += " and systemmetadata.date_modified < ?";
1416
                }
1417
                f2 = true;
1418
            }
1419
            
1420
            if(objectFormat != null)
1421
            {
1422
                if(!f1 && !f2)
1423
                {
1424
                    sql += " where object_format = ?";
1425
                }
1426
                else 
1427
                {
1428
                    sql += " and object_format = ?";
1429
                }
1430
                f3 = true;
1431
            }
1432
            
1433
            if(replicaStatus)
1434
            {
1435
                String currentNodeId = PropertyService.getInstance().getProperty("dataone.memberNodeId");
1436
                if(!f1 && !f2 && !f3)
1437
                {
1438
                    sql += " where authoritive_member_node != '" + currentNodeId.trim() + "'";
1439
                }
1440
                else
1441
                {
1442
                    sql += " and authoritive_member_node != '" + currentNodeId.trim() + "'";
1443
                }
1444
            }
1445
            
1446
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.querySystemMetadata");
1447
            serialNumber = dbConn.getCheckOutSerialNumber();
1448
            PreparedStatement stmt = dbConn.prepareStatement(sql);
1449
            
1450
            if(f1 && f2 && f3)
1451
            {
1452
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1453
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1454
                stmt.setString(3, objectFormat.toString());
1455
            }
1456
            else if(f1 && f2 && !f3)
1457
            {
1458
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1459
                stmt.setTimestamp(2, new Timestamp(endTime.getTime()));
1460
            }
1461
            else if(f1 && !f2 && f3)
1462
            {
1463
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1464
                stmt.setString(2, objectFormat.toString());
1465
            }
1466
            else if(f1 && !f2 && !f3)
1467
            {
1468
                stmt.setTimestamp(1, new Timestamp(startTime.getTime()));
1469
            }
1470
            else if(!f1 && f2 && f3)
1471
            {
1472
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1473
                stmt.setString(2, objectFormat.toString());
1474
            }
1475
            else if(!f1 && !f2 && f3)
1476
            {
1477
                stmt.setString(1, objectFormat.toString());
1478
            }
1479
            else if(!f1 && f2 && !f3)
1480
            {
1481
                stmt.setTimestamp(1, new Timestamp(endTime.getTime()));
1482
            }
1483
            
1484
            //logMetacat.debug("LISTOBJECTS QUERY: " + stmt.toString());
1485
            
1486
            ResultSet rs = stmt.executeQuery();
1487
            for(int i=0; i<start; i++)
1488
            {
1489
                if(rs.next())
1490
                {
1491
                    total++;
1492
                }
1493
                else
1494
                {
1495
                    break;
1496
                }
1497
            }
1498
            
1499
            int countIndex = 0;
1500
                        
1501
            while(rs.next()) 
1502
            {
1503
                total++;
1504
                if(countIndex >= count)
1505
                {
1506
                    break;
1507
                }
1508
                String guid = rs.getString(1);
1509
                //logMetacat.debug("query found doc with guid " + guid);
1510
                //Timestamp dateUploaded = rs.getTimestamp(2);
1511
                //String rightsHolder = rs.getString(3);
1512
                String checksum = rs.getString(4);
1513
                String checksumAlgorithm = rs.getString(5);
1514
                //String originMemberNode = rs.getString(6);
1515
                String authoritiveMemberNode = rs.getString(7);
1516
                Timestamp dateModified = rs.getTimestamp(8);
1517
                //String submitter = rs.getString(9);
1518
                String format = rs.getString(10);
1519
                String sz = rs.getString(11);
1520
                long size = 0;
1521
                if(sz != null && !sz.trim().equals(""))
1522
                {
1523
                    size = new Long(rs.getString(11)).longValue();
1524
                }
1525
                
1526
                ObjectInfo oi = new ObjectInfo();
1527
                
1528
                Identifier id = new Identifier();
1529
                id.setValue(guid);
1530
                oi.setIdentifier(id);
1531
                
1532
                oi.setDateSysMetadataModified(new Date(dateModified.getTime()));
1533
                
1534
                Checksum cs = new Checksum();
1535
                cs.setValue(checksum);
1536
                cs.setAlgorithm(ChecksumAlgorithm.valueOf(checksumAlgorithm));
1537
                //cs.setAlgorithm(ChecksumAlgorithm.convert(checksumAlgorithm));
1538
                oi.setChecksum(cs);
1539
                
1540
                ObjectFormat oFormat = ObjectFormat.convert(format);
1541
                if(oFormat != null)
1542
                {
1543
                    oi.setObjectFormat(oFormat);
1544
                }
1545
                else
1546
                { //if there is no object format, just default to text/plain
1547
                    oi.setObjectFormat(ObjectFormat.OCTET_STREAM);
1548
                }
1549
                                
1550
                oi.setSize(size);
1551
                
1552
                ol.addObjectInfo(oi);
1553
                countIndex++;
1554
            }
1555
            
1556
            while(rs.next())
1557
            { //expend the resultset to get the total count of possible rows
1558
                total++;
1559
            }
1560
        }
1561
        catch(Exception e)
1562
        {
1563
           e.printStackTrace();
1564
           logMetacat.error("Error querying system metadata: " + e.getMessage());
1565
        }
1566
        finally 
1567
        {
1568
            // Return database connection to the pool
1569
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1570
        }
1571
        
1572
        ol.setStart(start);
1573
        ol.setCount(ol.sizeObjectInfoList());
1574
        ol.setTotal(total);
1575
        
1576
        return ol;
1577
    }
1578
    
1579
    /**
1580
     * create a mapping in the identifier table
1581
     * @param guid
1582
     * @param localId
1583
     */
1584
    public void createMapping(String guid, String localId)
1585
    {        
1586
        
1587
        int serialNumber = -1;
1588
        DBConnection dbConn = null;
1589
        try {
1590

    
1591
            // Parse the localId into scope and rev parts
1592
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1593
            String docid = acc.getDocid();
1594
            int rev = 1;
1595
            if (acc.getRev() != null) {
1596
              rev = (new Integer(acc.getRev()).intValue());
1597
            }
1598

    
1599
            // Get a database connection from the pool
1600
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1601
            serialNumber = dbConn.getCheckOutSerialNumber();
1602

    
1603
            // Execute the insert statement
1604
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1605
            PreparedStatement stmt = dbConn.prepareStatement(query);
1606
            stmt.setString(1, guid);
1607
            stmt.setString(2, docid);
1608
            stmt.setInt(3, rev);
1609
            logMetacat.debug("mapping query: " + stmt.toString());
1610
            int rows = stmt.executeUpdate();
1611

    
1612
            stmt.close();
1613
        } catch (SQLException e) {
1614
            e.printStackTrace();
1615
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1616
                    + e.getMessage());
1617
        } catch (NumberFormatException e) {
1618
            e.printStackTrace();
1619
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1620
                    + e.getMessage());
1621
        } catch (AccessionNumberException e) {
1622
            e.printStackTrace();
1623
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1624
                    + e.getMessage());
1625
        } finally {
1626
            // Return database connection to the pool
1627
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1628
        }
1629
    }
1630
    
1631
    /**
1632
     * create the systemmetadata record
1633
     * @param guid
1634
     */
1635
    public void insertSystemMetadata(String guid)
1636
    {        
1637
        
1638
        int serialNumber = -1;
1639
        DBConnection dbConn = null;
1640
        try {
1641

    
1642
            // Get a database connection from the pool
1643
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1644
            serialNumber = dbConn.getCheckOutSerialNumber();
1645

    
1646
            // Execute the insert statement
1647
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1648
            PreparedStatement stmt = dbConn.prepareStatement(query);
1649
            stmt.setString(1, guid);
1650
            logMetacat.debug("system metadata query: " + stmt.toString());
1651
            int rows = stmt.executeUpdate();
1652

    
1653
            stmt.close();
1654
        } catch (Exception e) {
1655
            e.printStackTrace();
1656
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " 
1657
                    + e.getMessage());
1658
        } finally {
1659
            // Return database connection to the pool
1660
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1661
        }
1662
    }
1663
}
1664

    
(37-37/65)