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.client.ObjectFormatCache;
39
import org.dataone.service.exceptions.NotFound;
40
import org.dataone.service.types.AccessPolicy;
41
import org.dataone.service.types.AccessRule;
42
import org.dataone.service.types.Checksum;
43
import org.dataone.service.types.ChecksumAlgorithm;
44
import org.dataone.service.types.Identifier;
45
import org.dataone.service.types.NodeReference;
46
import org.dataone.service.types.ObjectFormat;
47
import org.dataone.service.types.ObjectFormatIdentifier;
48
import org.dataone.service.types.ObjectInfo;
49
import org.dataone.service.types.ObjectList;
50
import org.dataone.service.types.Permission;
51
import org.dataone.service.types.Replica;
52
import org.dataone.service.types.ReplicationPolicy;
53
import org.dataone.service.types.ReplicationStatus;
54
import org.dataone.service.types.Subject;
55
import org.dataone.service.types.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.util.DocumentUtil;
65

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

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

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

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

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

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

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

    
604
            // Execute the insert statement
605
            PreparedStatement stmt = dbConn.prepareStatement(sql);
606
            ResultSet rs = stmt.executeQuery();
607
            if (rs.next()) 
608
            {
609
                rev = rs.getInt(1);
610
                stmt.close();
611
            } 
612
            else
613
            {
614
                stmt.close();
615
                DBConnectionPool.returnDBConnection(dbConn, serialNumber);
616
                throw new McdbDocNotFoundException("While trying to get the latest rev, could not find document " + localId);
617
            }
618
        } 
619
        catch (SQLException e) 
620
        {
621
            logMetacat.error("Error while looking up the guid: " 
622
                    + e.getMessage());
623
        } 
624
        finally 
625
        {
626
            // Return database connection to the pool
627
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
628
        }
629
        return rev;
630
    }
631
    
632
    /**
633
     * return all local ids in the object store that do not have associated
634
     * system metadata
635
     */
636
    public List<String> getLocalIdsWithNoSystemMetadata()
637
    {
638
        Vector<String> ids = new Vector<String>();
639
        String sql = "select docid, rev from xml_documents " +
640
        		"where docid not in " +
641
        		"(select docid from identifier where guid in (select guid from systemmetadata)))";
642
        DBConnection dbConn = null;
643
        int serialNumber = -1;
644
        try 
645
        {
646
            // Get a database connection from the pool
647
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getLocalIdsWithNoSystemMetadata");
648
            serialNumber = dbConn.getCheckOutSerialNumber();
649

    
650
            // Execute the insert statement
651
            PreparedStatement stmt = dbConn.prepareStatement(sql);
652
            ResultSet rs = stmt.executeQuery();
653
            while (rs.next()) 
654
            {
655
                String localid = rs.getString(1);
656
                String rev = rs.getString(2);
657
                localid += "." + rev;
658
                logMetacat.debug("id to add SM for: " + localid);
659
                ids.add(localid);
660
            } 
661
            stmt.close();
662
        } 
663
        catch (SQLException e) 
664
        {
665
            logMetacat.error("Error while looking up the guid: " 
666
                    + e.getMessage());
667
        } 
668
        finally 
669
        {
670
            // Return database connection to the pool
671
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
672
        }
673
        
674
        return ids;
675
    }
676
    
677
    /**
678
     * return a listing of all local ids in the object store
679
     * @return a list of all local ids in metacat
680
     */
681
    public List<String> getAllLocalIds()
682
       throws Exception
683
    {
684
        Vector<String> ids = new Vector<String>();
685
        String sql = "select docid from xml_documents";
686
        DBConnection dbConn = null;
687
        int serialNumber = -1;
688
        try 
689
        {
690
            // Get a database connection from the pool
691
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getAllLocalIds");
692
            serialNumber = dbConn.getCheckOutSerialNumber();
693

    
694
            // Execute the insert statement
695
            PreparedStatement stmt = dbConn.prepareStatement(sql);
696
            ResultSet rs = stmt.executeQuery();
697
            while (rs.next()) 
698
            {
699
                String localid = rs.getString(1);
700
                ids.add(localid);
701
            } 
702
            stmt.close();
703
        } 
704
        catch (SQLException e) 
705
        {
706
            logMetacat.error("Error while looking up the guid: " 
707
                    + e.getMessage());
708
        } 
709
        finally 
710
        {
711
            // Return database connection to the pool
712
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
713
        }
714
        return ids;
715
    }
716
    
717
    /**
718
     * returns a list of system metadata-only guids since the given date
719
     * @return a list of system ids in metacat that do not correspond to objects
720
     * TODO: need to check which server they are on
721
     */
722
    public List<String> getUpdatedSystemMetadataIds(Date since)
723
       throws Exception
724
    {
725
        List<String> ids = new Vector<String>();
726
        String sql = 
727
        	"select guid from " + TYPE_SYSTEM_METADATA +
728
        	" where guid not in " +
729
        	" (select guid from " + TYPE_IDENTIFIER + ") " +
730
        	" and date_modified > ?";
731
        DBConnection dbConn = null;
732
        int serialNumber = -1;
733
        try 
734
        {
735
            // Get a database connection from the pool
736
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.getUpdatedSystemMetadataIds");
737
            serialNumber = dbConn.getCheckOutSerialNumber();
738

    
739
            // Execute the insert statement
740
            PreparedStatement stmt = dbConn.prepareStatement(sql);
741
            stmt.setDate(1, new java.sql.Date(since.getTime()));
742
            ResultSet rs = stmt.executeQuery();
743
            while (rs.next()) 
744
            {
745
                String guid = rs.getString(1);
746
                ids.add(guid);
747
            } 
748
            stmt.close();
749
        } 
750
        catch (SQLException e) 
751
        {
752
            logMetacat.error("Error while looking up the updated guids: " 
753
                    + e.getMessage());
754
        } 
755
        finally 
756
        {
757
            // Return database connection to the pool
758
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
759
        }
760
        return ids;
761
    }
762
    
763

    
764
    
765
    /**
766
     * Determine if an identifier exists already, returning true if so.
767
     * 
768
     * @param guid the global identifier to look up
769
     * @return boolean true if the identifier exists
770
     */
771
    public boolean identifierExists(String guid)
772
    {
773
        boolean idExists = false;
774
        try {
775
            String id = getLocalId(guid);
776
            if (id != null) {
777
                idExists = true;
778
            }
779
        } catch (McdbDocNotFoundException e) {
780
        	// try system metadata only
781
        	try {
782
        		idExists = systemMetadataExisits(guid);
783
            } catch (McdbDocNotFoundException e2) {
784
            	idExists = false;
785
            }
786
        }
787
        return idExists;
788
    }
789
    
790
    /**
791
     * 
792
     * @param guid
793
     * @param rev
794
     * @return
795
     */
796
    public String generateLocalId(String guid, int rev)
797
    {
798
        return generateLocalId(guid, rev, false);
799
    }
800

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

    
904
		DBConnection dbConn = null;
905
		int serialNumber = -1;
906
		try {
907
			// Get a database connection from the pool
908
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
909
			serialNumber = dbConn.getCheckOutSerialNumber();
910

    
911
			// Execute the insert statement
912
			PreparedStatement stmt = dbConn.prepareStatement(query);
913
			stmt.setString(1, guid);
914

    
915
			ResultSet rs = stmt.executeQuery();
916
			if (rs.next()) {
917
				exists = true;
918
			} else {
919
				throw new McdbDocNotFoundException(
920
						"No system metadata registered for guid " + guid);
921
			}
922

    
923
		} catch (SQLException e) {
924
			logMetacat.error("Error while looking up the system metadata: "
925
					+ e.getMessage());
926
		} finally {
927
			// Return database connection to the pool
928
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
929
		}
930

    
931
		return exists;
932
	}
933
    
934
    /**
935
     * creates a system metadata mapping and adds additional fields from sysmeta
936
     * to the table for quick searching.
937
     * 
938
     * @param guid the id to insert
939
     * @param localId the systemMetadata object to get the local id for
940
     * @throws McdbDocNotFoundException 
941
     */
942
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
943
    {
944
        insertSystemMetadata(sysmeta.getIdentifier().getValue());
945
        updateSystemMetadata(sysmeta);
946
    }
947
        
948
    
949
    /**
950
     * update a mapping
951
     * @param guid
952
     * @param localId
953
     */
954
    public void updateMapping(String guid, String localId)
955
    {
956
    	
957
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
958
        int serialNumber = -1;
959
        DBConnection dbConn = null;
960
        try {
961
            // Parse the localId into scope and rev parts
962
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
963
            String docid = acc.getDocid();
964
            int rev = 1;
965
            if(acc.getRev() != null)
966
            {
967
              rev = (new Integer(acc.getRev()).intValue());
968
            }
969

    
970
            // Get a database connection from the pool
971
            dbConn = 
972
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
973
            serialNumber = dbConn.getCheckOutSerialNumber();
974

    
975
            // Execute the update statement
976
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
977
            PreparedStatement stmt = dbConn.prepareStatement(query);
978
            stmt.setString(1, docid);
979
            stmt.setInt(2, rev);
980
            int rows = stmt.executeUpdate();
981

    
982
            stmt.close();
983
        } catch (SQLException e) {
984
            e.printStackTrace();
985
            logMetacat.error("SQL error while updating a mapping identifier: " 
986
                    + e.getMessage());
987
        } catch (NumberFormatException e) {
988
            e.printStackTrace();
989
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
990
                    + e.getMessage());
991
        } catch (AccessionNumberException e) {
992
            e.printStackTrace();
993
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
994
                    + e.getMessage());
995
        } finally {
996
            // Return database connection to the pool
997
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
998
        }
999
        logMetacat.debug("done updating mapping");
1000
    }
1001
        
1002
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1003
            String checksum, String checksumAlgorithm, String originMemberNode,
1004
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1005
            String guid, String objectFormat, long size, boolean replicationAllowed,
1006
            int numberReplicas)
1007
    {
1008
        DBConnection dbConn = null;
1009
        int serialNumber = -1;
1010
        
1011
        try {
1012
            // Get a database connection from the pool
1013
            dbConn = 
1014
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1015
            serialNumber = dbConn.getCheckOutSerialNumber();
1016

    
1017
            // Execute the insert statement
1018
            String query = "update " + TYPE_SYSTEM_METADATA + 
1019
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1020
                "origin_member_node, authoritive_member_node, date_modified, " +
1021
                "submitter, object_format, size, replication_allowed, number_replicas) " +
1022
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1023
            PreparedStatement stmt = dbConn.prepareStatement(query);
1024
            
1025
            //data values
1026
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1027
            stmt.setString(2, rightsHolder);
1028
            stmt.setString(3, checksum);
1029
            stmt.setString(4, checksumAlgorithm);
1030
            stmt.setString(5, originMemberNode);
1031
            stmt.setString(6, authoritativeMemberNode);
1032
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1033
            stmt.setString(8, submitter);
1034
            stmt.setString(9, objectFormat);
1035
            stmt.setString(10, new Long(size).toString());
1036
            stmt.setBoolean(11, replicationAllowed);
1037
            stmt.setInt(12, numberReplicas);
1038
            //where clause
1039
            stmt.setString(13, guid);
1040
            logMetacat.debug("stmt: " + stmt.toString());
1041
            //execute
1042
            int rows = stmt.executeUpdate();
1043

    
1044
            stmt.close();
1045
        } catch (SQLException e) {
1046
            e.printStackTrace();
1047
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1048
                    + e.getMessage());
1049
        } catch (NumberFormatException e) {
1050
            e.printStackTrace();
1051
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1052
                    + e.getMessage());
1053
        } finally {
1054
            // Return database connection to the pool
1055
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1056
        }
1057
    }
1058
    
1059
    private void insertSystemMetadataProvenance(String guid, String relationship, List<String> targetGuids)
1060
    {
1061
        DBConnection dbConn = null;
1062
        int serialNumber = -1;
1063
        
1064
        try {
1065
            // Get a database connection from the pool
1066
            dbConn = 
1067
                DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadataProvenance");
1068
            serialNumber = dbConn.getCheckOutSerialNumber();
1069

    
1070
            // remove existing values first
1071
            String delete = "delete from systemMetadataProvenance " + 
1072
            "where guid = ? and relationship = ?";
1073
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1074
	        //data values
1075
	        stmt.setString(1, guid);
1076
	        stmt.setString(2, relationship);
1077
	        //execute
1078
	        int deletedCount = stmt.executeUpdate();
1079
	        stmt.close();
1080
            
1081
            for (String targetGuid: targetGuids) {
1082
	            // Execute the insert statement
1083
	            String insert = "insert into systemMetadataProvenance " + 
1084
	                "(guid, relationship, target_guid) " +
1085
	                "values (?, ?, ?)";
1086
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1087
	            
1088
	            //data values
1089
	            insertStatement.setString(1, guid);
1090
	            insertStatement.setString(2, relationship);
1091
	            insertStatement.setString(3, targetGuid);
1092
	            //execute
1093
	            int rows = insertStatement.executeUpdate();
1094
	            insertStatement.close();
1095
            }
1096
        } catch (SQLException e) {
1097
            logMetacat.error("SQL error while adding systemMetadataProvenance for: " + guid, e); 
1098
        } finally {
1099
            // Return database connection to the pool
1100
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1101
        }
1102
    }
1103
    
1104
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1105
    {
1106
        DBConnection dbConn = null;
1107
        int serialNumber = -1;
1108
        
1109
        try {
1110
            // Get a database connection from the pool
1111
            dbConn = 
1112
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1113
            serialNumber = dbConn.getCheckOutSerialNumber();
1114

    
1115
            // remove existing values first
1116
            String delete = "delete from systemMetadataReplicationPolicy " + 
1117
            "where guid = ? and policy = ?";
1118
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1119
	        //data values
1120
	        stmt.setString(1, guid);
1121
	        stmt.setString(2, policy);
1122
	        //execute
1123
	        int deletedCount = stmt.executeUpdate();
1124
	        stmt.close();
1125
            
1126
            for (String memberNode: memberNodes) {
1127
	            // Execute the insert statement
1128
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1129
	                "(guid, policy, member_node) " +
1130
	                "values (?, ?, ?)";
1131
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1132
	            
1133
	            //data values
1134
	            insertStatement.setString(1, guid);
1135
	            insertStatement.setString(2, policy);
1136
	            insertStatement.setString(3, memberNode);
1137
	            //execute
1138
	            int rows = insertStatement.executeUpdate();
1139
	            insertStatement.close();
1140
            }
1141
        } catch (SQLException e) {
1142
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1143
        } finally {
1144
            // Return database connection to the pool
1145
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1146
        }
1147
    }
1148
    
1149
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1150
        DBConnection dbConn = null;
1151
        int serialNumber = -1;
1152
        
1153
        try {
1154
            // Get a database connection from the pool
1155
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1156
            serialNumber = dbConn.getCheckOutSerialNumber();
1157

    
1158
            // remove existing values first
1159
            String delete = "delete from systemMetadataReplicationStatus " + 
1160
            "where guid = ?";
1161
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1162
	        //data values
1163
	        stmt.setString(1, guid);
1164
	        //execute
1165
	        int deletedCount = stmt.executeUpdate();
1166
	        stmt.close();
1167
            
1168
            for (Replica replica: replicas) {
1169
	            // Execute the insert statement
1170
	            String insert = "insert into systemMetadataReplicationStatus " + 
1171
	                "(guid, member_node, status, date_verified) " +
1172
	                "values (?, ?, ?, ?)";
1173
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1174
	            
1175
	            //data values
1176
	            String memberNode = replica.getReplicaMemberNode().getValue();
1177
	            String status = replica.getReplicationStatus().toString();
1178
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1179
	            insertStatement.setString(1, guid);
1180
	            insertStatement.setString(2, memberNode);
1181
	            insertStatement.setString(3, status);
1182
	            insertStatement.setDate(4, sqlDate);
1183

    
1184
	            //execute
1185
	            int rows = insertStatement.executeUpdate();
1186
	            insertStatement.close();
1187
            }
1188
        } catch (SQLException e) {
1189
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1190
        } finally {
1191
            // Return database connection to the pool
1192
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1193
        }
1194
    }
1195
    
1196
    /**
1197
     * Insert the system metadata fields into the db
1198
     * @param sm
1199
     * @throws McdbDocNotFoundException 
1200
     */
1201
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1202
    	
1203
        Boolean replicationAllowed = false;
1204
		Integer numberReplicas = -1;
1205
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1206
    	if (replicationPolicy != null) {
1207
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1208
    		numberReplicas = replicationPolicy.getNumberReplicas();
1209
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1210
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1211
    	}
1212

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

    
1650
            // Parse the localId into scope and rev parts
1651
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1652
            String docid = acc.getDocid();
1653
            int rev = 1;
1654
            if (acc.getRev() != null) {
1655
              rev = (new Integer(acc.getRev()).intValue());
1656
            }
1657

    
1658
            // Get a database connection from the pool
1659
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1660
            serialNumber = dbConn.getCheckOutSerialNumber();
1661

    
1662
            // Execute the insert statement
1663
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1664
            PreparedStatement stmt = dbConn.prepareStatement(query);
1665
            stmt.setString(1, guid);
1666
            stmt.setString(2, docid);
1667
            stmt.setInt(3, rev);
1668
            logMetacat.debug("mapping query: " + stmt.toString());
1669
            int rows = stmt.executeUpdate();
1670

    
1671
            stmt.close();
1672
        } catch (SQLException e) {
1673
            e.printStackTrace();
1674
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1675
                    + e.getMessage());
1676
        } catch (NumberFormatException e) {
1677
            e.printStackTrace();
1678
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1679
                    + e.getMessage());
1680
        } catch (AccessionNumberException e) {
1681
            e.printStackTrace();
1682
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1683
                    + e.getMessage());
1684
        } finally {
1685
            // Return database connection to the pool
1686
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1687
        }
1688
    }
1689
    
1690
    /**
1691
     * create the systemmetadata record
1692
     * @param guid
1693
     */
1694
    public void insertSystemMetadata(String guid)
1695
    {        
1696
        
1697
        int serialNumber = -1;
1698
        DBConnection dbConn = null;
1699
        try {
1700

    
1701
            // Get a database connection from the pool
1702
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1703
            serialNumber = dbConn.getCheckOutSerialNumber();
1704

    
1705
            // Execute the insert statement
1706
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid) values (?)";
1707
            PreparedStatement stmt = dbConn.prepareStatement(query);
1708
            stmt.setString(1, guid);
1709
            logMetacat.debug("system metadata query: " + stmt.toString());
1710
            int rows = stmt.executeUpdate();
1711

    
1712
            stmt.close();
1713
        } catch (Exception e) {
1714
            e.printStackTrace();
1715
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " 
1716
                    + e.getMessage());
1717
        } finally {
1718
            // Return database connection to the pool
1719
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1720
        }
1721
    }
1722
}
1723

    
(37-37/65)