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.Session;
55
import org.dataone.service.types.Subject;
56
import org.dataone.service.types.SystemMetadata;
57

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

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

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

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

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

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

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

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

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

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

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

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

    
765
    
766
    /**
767
     * Determine if an identifier exists already, returning true if so.
768
     * 
769
     * @param guid the global identifier to look up
770
     * @return boolean true if the identifier exists
771
     */
772
    public boolean identifierExists(String guid)
773
    {
774
        boolean idExists = false;
775
        try {
776
            String id = getLocalId(guid);
777
            if (id != null) {
778
                idExists = true;
779
            }
780
        } catch (McdbDocNotFoundException e) {
781
        	// try system metadata only
782
        	try {
783
        		boolean provisional = false;
784
        		idExists = systemMetadataExisits(guid, provisional);
785
            } catch (McdbDocNotFoundException e2) {
786
            	idExists = false;
787
            }
788
        }
789
        return idExists;
790
    }
791
    
792
    public boolean hasReservation(Identifier pid, Session session) {
793
    	// check if it was reserved
794
      	boolean reserved = false;
795
      	try {
796
    		// check that we reserved it
797
    		if (IdentifierManager.getInstance().systemMetadataExisits(pid.getValue(), true)) {    		    	
798
    	    	SystemMetadata provisionalMetadata = IdentifierManager.getInstance().getSystemMetadata(pid.getValue());
799
    	    	Subject rightsHolder = provisionalMetadata.getRightsHolder();
800
    	    	// TODO: check groups?
801
    	    	if (session.getSubject().equals(rightsHolder)) {
802
    	    		reserved = true;
803
    	    	}
804
    		}
805
    	} catch (McdbDocNotFoundException e) {
806
    		reserved = false;
807
    	}
808
    	return reserved;
809
      }
810
    
811
    /**
812
     * 
813
     * @param guid
814
     * @param rev
815
     * @return
816
     */
817
    public String generateLocalId(String guid, int rev)
818
    {
819
        return generateLocalId(guid, rev, false);
820
    }
821

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

    
925
		DBConnection dbConn = null;
926
		int serialNumber = -1;
927
		try {
928
			// Get a database connection from the pool
929
			dbConn = DBConnectionPool.getDBConnection("IdentifierManager.systemMetadataExisits");
930
			serialNumber = dbConn.getCheckOutSerialNumber();
931

    
932
			// Execute the insert statement
933
			PreparedStatement stmt = dbConn.prepareStatement(query);
934
			stmt.setString(1, guid);
935
			stmt.setBoolean(2, provisional);
936
			ResultSet rs = stmt.executeQuery();
937
			if (rs.next()) {
938
				exists = true;
939
			} else {
940
				throw new McdbDocNotFoundException(
941
						"No system metadata registered for guid " + guid);
942
			}
943

    
944
		} catch (SQLException e) {
945
			logMetacat.error("Error while looking up the system metadata: "
946
					+ e.getMessage());
947
		} finally {
948
			// Return database connection to the pool
949
			DBConnectionPool.returnDBConnection(dbConn, serialNumber);
950
		}
951

    
952
		return exists;
953
	}
954
    
955
    /**
956
     * creates a system metadata mapping and adds additional fields from sysmeta
957
     * to the table for quick searching.
958
     * 
959
     * @param guid the id to insert
960
     * @param localId the systemMetadata object to get the local id for
961
     * @throws McdbDocNotFoundException 
962
     */
963
    public void createSystemMetadata(SystemMetadata sysmeta) throws McdbDocNotFoundException
964
    {
965
    	String guid = sysmeta.getIdentifier().getValue();
966
    	// remove any provisional records -- it is the responsibility of the caller to check this
967
    	if (systemMetadataExisits(guid, true)) {
968
    		deleteSystemMetadata(guid);
969
    	}
970
    	// insert the true record
971
        insertSystemMetadata(guid, false);
972
        updateSystemMetadata(sysmeta);
973
    }
974
        
975
    
976
    /**
977
     * update a mapping
978
     * @param guid
979
     * @param localId
980
     */
981
    public void updateMapping(String guid, String localId)
982
    {
983
    	
984
        logMetacat.debug("$$$$$$$$$$$$$$ updating mapping table");
985
        int serialNumber = -1;
986
        DBConnection dbConn = null;
987
        try {
988
            // Parse the localId into scope and rev parts
989
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
990
            String docid = acc.getDocid();
991
            int rev = 1;
992
            if(acc.getRev() != null)
993
            {
994
              rev = (new Integer(acc.getRev()).intValue());
995
            }
996

    
997
            // Get a database connection from the pool
998
            dbConn = 
999
                DBConnectionPool.getDBConnection("IdentifierManager.updateMapping");
1000
            serialNumber = dbConn.getCheckOutSerialNumber();
1001

    
1002
            // Execute the update statement
1003
            String query = "update " + TYPE_IDENTIFIER + " set (docid, rev) = (?, ?) where guid='" + guid + "'";
1004
            PreparedStatement stmt = dbConn.prepareStatement(query);
1005
            stmt.setString(1, docid);
1006
            stmt.setInt(2, rev);
1007
            int rows = stmt.executeUpdate();
1008

    
1009
            stmt.close();
1010
        } catch (SQLException e) {
1011
            e.printStackTrace();
1012
            logMetacat.error("SQL error while updating a mapping identifier: " 
1013
                    + e.getMessage());
1014
        } catch (NumberFormatException e) {
1015
            e.printStackTrace();
1016
            logMetacat.error("NumberFormat error while updating a mapping identifier: " 
1017
                    + e.getMessage());
1018
        } catch (AccessionNumberException e) {
1019
            e.printStackTrace();
1020
            logMetacat.error("AccessionNumber error while updating a mapping identifier: " 
1021
                    + e.getMessage());
1022
        } finally {
1023
            // Return database connection to the pool
1024
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1025
        }
1026
        logMetacat.debug("done updating mapping");
1027
    }
1028
        
1029
    private void updateSystemMetadataFields(long dateUploaded, String rightsHolder,
1030
            String checksum, String checksumAlgorithm, String originMemberNode,
1031
            String authoritativeMemberNode, long modifiedDate, String submitter, 
1032
            String guid, String objectFormat, long size, boolean replicationAllowed,
1033
            int numberReplicas)
1034
    {
1035
        DBConnection dbConn = null;
1036
        int serialNumber = -1;
1037
        
1038
        try {
1039
            // Get a database connection from the pool
1040
            dbConn = 
1041
                DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1042
            serialNumber = dbConn.getCheckOutSerialNumber();
1043

    
1044
            // Execute the insert statement
1045
            String query = "update " + TYPE_SYSTEM_METADATA + 
1046
                " set (date_uploaded, rights_holder, checksum, checksum_algorithm, " +
1047
                "origin_member_node, authoritive_member_node, date_modified, " +
1048
                "submitter, object_format, size, replication_allowed, number_replicas) " +
1049
                "= (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?) where guid = ?";
1050
            PreparedStatement stmt = dbConn.prepareStatement(query);
1051
            
1052
            //data values
1053
            stmt.setTimestamp(1, new java.sql.Timestamp(dateUploaded));
1054
            stmt.setString(2, rightsHolder);
1055
            stmt.setString(3, checksum);
1056
            stmt.setString(4, checksumAlgorithm);
1057
            stmt.setString(5, originMemberNode);
1058
            stmt.setString(6, authoritativeMemberNode);
1059
            stmt.setTimestamp(7, new java.sql.Timestamp(modifiedDate));
1060
            stmt.setString(8, submitter);
1061
            stmt.setString(9, objectFormat);
1062
            stmt.setString(10, new Long(size).toString());
1063
            stmt.setBoolean(11, replicationAllowed);
1064
            stmt.setInt(12, numberReplicas);
1065
            //where clause
1066
            stmt.setString(13, guid);
1067
            logMetacat.debug("stmt: " + stmt.toString());
1068
            //execute
1069
            int rows = stmt.executeUpdate();
1070

    
1071
            stmt.close();
1072
        } catch (SQLException e) {
1073
            e.printStackTrace();
1074
            logMetacat.error("insertAdditionalSystemMetadataFields: SQL error while creating a mapping to the system metadata identifier: " 
1075
                    + e.getMessage());
1076
        } catch (NumberFormatException e) {
1077
            e.printStackTrace();
1078
            logMetacat.error("insertAdditionalSystemMetadataFields: NumberFormat error while creating a mapping to the system metadata identifier: " 
1079
                    + e.getMessage());
1080
        } finally {
1081
            // Return database connection to the pool
1082
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1083
        }
1084
    }
1085
    
1086
    private void insertSystemMetadataProvenance(String guid, String relationship, List<String> targetGuids)
1087
    {
1088
        DBConnection dbConn = null;
1089
        int serialNumber = -1;
1090
        
1091
        try {
1092
            // Get a database connection from the pool
1093
            dbConn = 
1094
                DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadataProvenance");
1095
            serialNumber = dbConn.getCheckOutSerialNumber();
1096

    
1097
            // remove existing values first
1098
            String delete = "delete from systemMetadataProvenance " + 
1099
            "where guid = ? and relationship = ?";
1100
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1101
	        //data values
1102
	        stmt.setString(1, guid);
1103
	        stmt.setString(2, relationship);
1104
	        //execute
1105
	        int deletedCount = stmt.executeUpdate();
1106
	        stmt.close();
1107
            
1108
            for (String targetGuid: targetGuids) {
1109
	            // Execute the insert statement
1110
	            String insert = "insert into systemMetadataProvenance " + 
1111
	                "(guid, relationship, target_guid) " +
1112
	                "values (?, ?, ?)";
1113
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1114
	            
1115
	            //data values
1116
	            insertStatement.setString(1, guid);
1117
	            insertStatement.setString(2, relationship);
1118
	            insertStatement.setString(3, targetGuid);
1119
	            //execute
1120
	            int rows = insertStatement.executeUpdate();
1121
	            insertStatement.close();
1122
            }
1123
        } catch (SQLException e) {
1124
            logMetacat.error("SQL error while adding systemMetadataProvenance for: " + guid, e); 
1125
        } finally {
1126
            // Return database connection to the pool
1127
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1128
        }
1129
    }
1130
    
1131
    private void insertReplicationPolicy(String guid, String policy, List<String> memberNodes)
1132
    {
1133
        DBConnection dbConn = null;
1134
        int serialNumber = -1;
1135
        
1136
        try {
1137
            // Get a database connection from the pool
1138
            dbConn = 
1139
                DBConnectionPool.getDBConnection("IdentifierManager.insertReplicationPolicy");
1140
            serialNumber = dbConn.getCheckOutSerialNumber();
1141

    
1142
            // remove existing values first
1143
            String delete = "delete from systemMetadataReplicationPolicy " + 
1144
            "where guid = ? and policy = ?";
1145
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1146
	        //data values
1147
	        stmt.setString(1, guid);
1148
	        stmt.setString(2, policy);
1149
	        //execute
1150
	        int deletedCount = stmt.executeUpdate();
1151
	        stmt.close();
1152
            
1153
            for (String memberNode: memberNodes) {
1154
	            // Execute the insert statement
1155
	            String insert = "insert into systemMetadataReplicationPolicy " + 
1156
	                "(guid, policy, member_node) " +
1157
	                "values (?, ?, ?)";
1158
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1159
	            
1160
	            //data values
1161
	            insertStatement.setString(1, guid);
1162
	            insertStatement.setString(2, policy);
1163
	            insertStatement.setString(3, memberNode);
1164
	            //execute
1165
	            int rows = insertStatement.executeUpdate();
1166
	            insertStatement.close();
1167
            }
1168
        } catch (SQLException e) {
1169
            logMetacat.error("SQL error while adding systemMetadataReplicationPolicy for: " + guid, e); 
1170
        } finally {
1171
            // Return database connection to the pool
1172
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1173
        }
1174
    }
1175
    
1176
    private void insertReplicationStatus(String guid, List<Replica> replicas) {
1177
        DBConnection dbConn = null;
1178
        int serialNumber = -1;
1179
        
1180
        try {
1181
            // Get a database connection from the pool
1182
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertReplicas");
1183
            serialNumber = dbConn.getCheckOutSerialNumber();
1184

    
1185
            // remove existing values first
1186
            String delete = "delete from systemMetadataReplicationStatus " + 
1187
            "where guid = ?";
1188
	        PreparedStatement stmt = dbConn.prepareStatement(delete);
1189
	        //data values
1190
	        stmt.setString(1, guid);
1191
	        //execute
1192
	        int deletedCount = stmt.executeUpdate();
1193
	        stmt.close();
1194
            
1195
            for (Replica replica: replicas) {
1196
	            // Execute the insert statement
1197
	            String insert = "insert into systemMetadataReplicationStatus " + 
1198
	                "(guid, member_node, status, date_verified) " +
1199
	                "values (?, ?, ?, ?)";
1200
	            PreparedStatement insertStatement = dbConn.prepareStatement(insert);
1201
	            
1202
	            //data values
1203
	            String memberNode = replica.getReplicaMemberNode().getValue();
1204
	            String status = replica.getReplicationStatus().toString();
1205
	            java.sql.Date sqlDate = new java.sql.Date(replica.getReplicaVerified().getTime());
1206
	            insertStatement.setString(1, guid);
1207
	            insertStatement.setString(2, memberNode);
1208
	            insertStatement.setString(3, status);
1209
	            insertStatement.setDate(4, sqlDate);
1210

    
1211
	            //execute
1212
	            int rows = insertStatement.executeUpdate();
1213
	            insertStatement.close();
1214
            }
1215
        } catch (SQLException e) {
1216
            logMetacat.error("SQL error while adding systemMetadataReplicationStatus for: " + guid, e); 
1217
        } finally {
1218
            // Return database connection to the pool
1219
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1220
        }
1221
    }
1222
    
1223
    /**
1224
     * Insert the system metadata fields into the db
1225
     * @param sm
1226
     * @throws McdbDocNotFoundException 
1227
     */
1228
    public void updateSystemMetadata(SystemMetadata sm) throws McdbDocNotFoundException {
1229
    	
1230
        Boolean replicationAllowed = false;
1231
		Integer numberReplicas = -1;
1232
    	ReplicationPolicy replicationPolicy = sm.getReplicationPolicy();
1233
    	if (replicationPolicy != null) {
1234
    		replicationAllowed = replicationPolicy.getReplicationAllowed();
1235
    		numberReplicas = replicationPolicy.getNumberReplicas();
1236
    		replicationAllowed = replicationAllowed == null ? false: replicationAllowed;
1237
    		numberReplicas = numberReplicas == null ? -1: numberReplicas;
1238
    	}
1239

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

    
1677
            // Parse the localId into scope and rev parts
1678
            AccessionNumber acc = new AccessionNumber(localId, "NOACTION");
1679
            String docid = acc.getDocid();
1680
            int rev = 1;
1681
            if (acc.getRev() != null) {
1682
              rev = (new Integer(acc.getRev()).intValue());
1683
            }
1684

    
1685
            // Get a database connection from the pool
1686
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.createMapping");
1687
            serialNumber = dbConn.getCheckOutSerialNumber();
1688

    
1689
            // Execute the insert statement
1690
            String query = "insert into " + TYPE_IDENTIFIER + " (guid, docid, rev) values (?, ?, ?)";
1691
            PreparedStatement stmt = dbConn.prepareStatement(query);
1692
            stmt.setString(1, guid);
1693
            stmt.setString(2, docid);
1694
            stmt.setInt(3, rev);
1695
            logMetacat.debug("mapping query: " + stmt.toString());
1696
            int rows = stmt.executeUpdate();
1697

    
1698
            stmt.close();
1699
        } catch (SQLException e) {
1700
            e.printStackTrace();
1701
            logMetacat.error("createGenericMapping: SQL error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1702
                    + e.getMessage());
1703
        } catch (NumberFormatException e) {
1704
            e.printStackTrace();
1705
            logMetacat.error("createGenericMapping: NumberFormat error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1706
                    + e.getMessage());
1707
        } catch (AccessionNumberException e) {
1708
            e.printStackTrace();
1709
            logMetacat.error("createGenericMapping: AccessionNumber error while creating a mapping to the " + TYPE_IDENTIFIER + " identifier: " 
1710
                    + e.getMessage());
1711
        } finally {
1712
            // Return database connection to the pool
1713
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1714
        }
1715
    }
1716
    
1717
    /**
1718
     * create the systemmetadata record
1719
     * @param guid
1720
     */
1721
    private void insertSystemMetadata(String guid, boolean provisional)
1722
    {        
1723
        
1724
        int serialNumber = -1;
1725
        DBConnection dbConn = null;
1726
        try {
1727

    
1728
            // Get a database connection from the pool
1729
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1730
            serialNumber = dbConn.getCheckOutSerialNumber();
1731

    
1732
            // Execute the insert statement
1733
            String query = "insert into " + TYPE_SYSTEM_METADATA + " (guid, provisional) values (?, ?)";
1734
            PreparedStatement stmt = dbConn.prepareStatement(query);
1735
            stmt.setString(1, guid);
1736
            stmt.setBoolean(2, provisional);
1737
            logMetacat.debug("system metadata query: " + stmt.toString());
1738
            int rows = stmt.executeUpdate();
1739

    
1740
            stmt.close();
1741
        } catch (Exception e) {
1742
            e.printStackTrace();
1743
            logMetacat.error("Error while creating " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1744
        } finally {
1745
            // Return database connection to the pool
1746
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1747
        }
1748
    }
1749
    
1750
    private void deleteSystemMetadata(String guid)
1751
    {        
1752
        
1753
        int serialNumber = -1;
1754
        DBConnection dbConn = null;
1755
        try {
1756

    
1757
            // Get a database connection from the pool
1758
            dbConn = DBConnectionPool.getDBConnection("IdentifierManager.insertSystemMetadata");
1759
            serialNumber = dbConn.getCheckOutSerialNumber();
1760

    
1761
            // Execute the statement
1762
            String query = "delete from " + TYPE_SYSTEM_METADATA + " where guid = ? ";
1763
            PreparedStatement stmt = dbConn.prepareStatement(query);
1764
            stmt.setString(1, guid);
1765
            logMetacat.debug("delete system metadata: " + stmt.toString());
1766
            int rows = stmt.executeUpdate();
1767

    
1768
            stmt.close();
1769
        } catch (Exception e) {
1770
            e.printStackTrace();
1771
            logMetacat.error("Error while deleting " + TYPE_SYSTEM_METADATA + " record: " + guid, e );
1772
        } finally {
1773
            // Return database connection to the pool
1774
            DBConnectionPool.returnDBConnection(dbConn, serialNumber);
1775
        }
1776
    }
1777
}
1778

    
(37-37/65)